在表达式中
data Frank a b = Frank {frankField :: b a} deriving (Show)
{frankField :: b a}
是什么意思?
{frankField :: b a}
是类型构造函数吗?如果是这样,参数应该看起来像b->a
而不是b a
吗?
答案 0 :(得分:4)
Frank
是类型* -> (* -> *) -> *
的类型,即它采用类型a
(类型*
),例如Int
,{{ 1}}或Char
;一元类型 constructor String
(类型b
),例如* -> *
或Maybe
。 (您可以使用GHCi中的Either String
或:kind
命令检查类型的种类。)
它有一个构造函数,也称为:k
,其中包含一个类型为Frank
的类型为b a
的 field (不是构造函数),例如类型frankField
中的frankField
类型为Frank Int Maybe
,因为Maybe Int
= b
并且Maybe
= a
,因此Int
= b a
。
此定义使用 record 表示法为字段命名—您也可以只写Maybe Int
使其保持匿名,但是命名字段的好处是您可以可以使用显式记录语法构造一个data Frank a b = Frank (b a)
值:
Frank
或修改值:
frank1 :: Frank Int Maybe
frank1 = Frank { frankField = Just 1 }
或按名称访问该字段:
frank2 :: Frank Int Maybe
frank2 = frank1 { frankField = Nothing }
当构造函数包含多个字段时,这更方便且更常见;另外,当类型只包装一个值时,通常会看到value :: Maybe Int
value = frankField frank1
而不是newtype
,因为data
的开销较小,懒惰语义也稍有不同。