以下两个代码都可以使用Foundation(并且Prelude作为合格的导入P)进行编译,并返回期望的字符串。
-- the inferred type
blahhh :: Item [Char]
blahhh = P.head $ toList ("blahh de blahh de blahh" :: [Item [Char]])
blahh2 :: [Char]
blahh2 = blahhh : ": Should be a b"
和
blahhh :: Char
blahhh = P.head $ toList ("blahh de blahh de blahh" :: [Char])
blahh2 :: [Char]
blahh2 = blahhh : ": Should be a b"
起初我发现这有点令人困惑。最初,我认为我需要一些Item
数据类型来在列表中进行模式匹配。
然后我意识到Item
从列表中提取了项目类型(如记录所示),所以Item [Char] == Char
。
我的问题是这种(Item
)和类似类型的目的是什么?额外的复杂性给您带来什么?
答案 0 :(得分:2)
您是正确的,Item
在使用[Char]
时只会增加复杂性。但是,Item
背后的想法是它也可以用于其他类型。例如,Item (Array ty)
是ty
,Item CSV
是Row
,Item Bitmap
是Bool
等。这使我们的函数更具多态性,因此它们可能是通常更常用:例如,取fromList :: [Item l] -> l
,根据l
是什么,可在以下任何情况下使用:
fromList :: [a] -> [a]
fromList :: [ty] -> Array ty
fromList :: [Row] -> CSV
fromList :: [Bool] -> Bitmap
比拥有一堆函数fromListArray
,fromRowsCSV
等更容易使用。
答案 1 :(得分:2)
Item
不是普通类型,而是“类型同义词家族”(名称不正确),它是一种类型级别的函数。如您所见,type instance Item [a] = a
意味着您可以用“ Item [a]
”替换“ a
”(在类型签名中)“ snd (_,y) = y
”,就像函数声明snd (1,2)
意味着您可以替换“ 2
和“ Item a
”。
a
的要点是它使您可以编写关于参数{{1}} 通用的代码。或者更确切地说,它使您可以表达这种功能的类型。
通常对于这样的类型同义词家族有用,它需要与类型类配对:后者可让您为不同类型定义不同的行为,前者允许输出类型取决于输入的类型。多参数类型类+功能依赖项可以实现相同的目标。
当类型家族被定义为类型类的一部分时(由于上面的段落中所述的关系),有时(又令人困惑地)将它们称为“关联类型”,但这是一个肤浅的句法。
传统上,类型族是“开放的”(如类型类),但是现在有封闭型族可以帮助递归。