我一直在浏览GHC Generics documentation here,似乎示例代码不正确。我遇到麻烦的部分是:
type RepUserTree a =
-- A UserTree is either a Leaf, which has no arguments
U1
-- ... or it is a Node, which has three arguments that we put in a product
:+: a :*: UserTree a :*: UserTree a
假设(:*:)
类型运算符被定义为data (:*:) f g p = f p :*: g p
,正如预期的那样,上面的代码位给出了类错误:
Blockquotetest.hs:26:13: error:
• Expecting one fewer argument to ‘UserTree a’
Expected kind ‘* -> *’, but ‘UserTree a’ has kind ‘*’
• In the first argument of ‘:*:’, namely ‘UserTree a’
In the second argument of ‘:*:’, namely ‘UserTree a :*: UserTree a’
In the second argument of ‘:+:’, namely
‘a :*: (UserTree a :*: UserTree a)’
文档是否不正确?我错过了一个扩展,使上述工作?我不确定如何改变上面的内容进行编译。
答案 0 :(得分:0)
这只是一个虚拟的例子,让您了解它正在做什么,因为细节有点复杂。但是可能值得理解为什么它不能编译,因为如果你想在Haskell中进行任何类型级别的编程,那么理解在这些情况下出了什么问题是很好的。
如果查看(:+:)
和(:*:)
的类型参数,可以看到它们分别采用三种类型f g p
。他们都很善良* -> * -> * -> *
。
data (:+:) f g p = L1 (f p) | R1 (g p)
data (:*:) f g p = f p :*: g p
和p
已提供给f
和g
,因此我们知道f
和g
必须至少是* -> *
种。 UserTree
类型的类型为* -> *
。
data UserTree a = Node a (UserTree a) (UserTree a) | Leaf
但是在声明中我们有UserTree a
,它是*
种类,而什么(:* :)期待至少有两种事物* -> *
。
type RepUserTree a = U1 :+: a :*: UserTree a :*: UserTree a
如果你删除a
,你就可以编译它。
type RepUserTree a = U1 :+: a :*: UserTree :*: UserTree
现在查看U1
,K1
和M1
,它们都以p
参数结尾。请注意,在RealRepUserTree
示例中,U1
,K1
和M1
所有类型都少于一个。这些符合(:+:)
和(:*:)
的要求。