能否在关联数据类型中使用DataKinds?Haskell类型类报错咨询
在关联类型中使用DataKinds的正确姿势
嘿,这个问题我之前踩过坑!咱们一步步理清问题和解决办法:
首先,你的错误根源
你遇到的Not in scope: data constructor ‘Bool’错误,首先大概率是没启用DataKinds扩展——没有这个扩展的话,编译器会把'Bool当成是引用一个名为Bool的数据构造器,而不是把Bool类型提升成的种类。
但更核心的问题是:你混淆了关联数据类型(data family)和类型家族(type family)的用途,以及DataKinds提升后的种类的本质。
DataKinds把Bool这样的代数类型提升成了种类'Bool,这个种类的“居民”是类型级别的常量:'True和'False。而关联数据类型(data MyBool b :: 'Bool这种写法)是用来定义值级别的数据类型的,这类数据类型的种类默认是Type(也就是旧语法里的*)——你没法让一个数据类型属于'Bool种类,因为这两个种类是完全不同的分支。
正确的解决办法:用关联类型家族
如果你的需求是:为每个BoolHolding的实例h,关联一个类型级别的布尔值(属于'Bool种类),那应该用关联类型家族(type family)而不是关联数据类型。
步骤1:启用必要的扩展
首先在代码顶部加上这些扩展:
{-# LANGUAGE DataKinds, TypeFamilies, KindSignatures #-}
步骤2:重写类型类
把关联数据类型改成关联类型家族:
class BoolHolding h where type MyBool h :: 'Bool -- 指定MyBool h的种类是提升后的Bool
步骤3:编写实例
现在你可以为不同的h关联对应的类型级布尔值了:
-- 让Int对应的类型布尔是'True instance BoolHolding Int where type MyBool Int = 'True -- 让String对应的类型布尔是'False instance BoolHolding String where type MyBool String = 'False
为什么不能用关联数据类型?
简单来说:
- 关联数据类型(data family)是用来定义可以生成值的数据类型的,这类类型的种类必然是
Type或者k -> Type这样的函数种类(比如Maybe的种类是Type -> Type)。 - 而
'Bool种类的成员是编译时的类型常量,它们没有对应的“值构造器”——你没法创建一个类型为'True的值,因为'True是类型级别的东西,不是值级别的数据类型。
如果需要同时关联值级别的布尔和类型级别的布尔,可以考虑使用singletons库,它能帮你自动生成类型和值的对应关系,但这属于进阶用法了。
内容的提问来源于stack exchange,提问作者Anders Miltner
相关产品推荐
相关产品推荐

