我在“Real World Haskell”一书中找到了这样的代码,p68
data Tree a = Node a (Tree a) (Tree a)
| Empty
deriving (Show)
nodeAreSame (Node a _ _) (Node b _ _)
| a == b = Just a
nodeAreSame _ _ = Nothing
我的问题是:Just
数据构造函数做了什么工作?当我删除它时,我会收到类似
(in ghci)
......
<Main *> nodeAreSame (Node 3 Empty Empty) (Node 3 Empty Empty))
<interactive>:1:16:
No instance for (Num (Maybe a))
......
但是当我尝试比较“Just”和“No Just”版本之间的类型差异时:
nodeAreSameJust :: (Eq t) => Tree t -> Tree t -> Maybe t
nodeAreSameNoJust :: (Eq a) => Tree (Maybe a) -> Tree (Maybe a) -> Maybe a
那么这里的关键点是什么?这是否意味着当我在节点中放置类型为a
的var时,该函数将不会输出类型为a
的节点,因此会出错?
答案 0 :(得分:12)
事实上,Just
缺席不会使其输入错误。
这是交易。代码
nodeAreSame (Node a _ _) (Node b _ _)
| a == b = a
nodeAreSame _ _ = Nothing
如果某些
a
的{{1}}和b
类型为Maybe t
,那么 类型为井,因为这是{t
的类型1}}。因此,类型系统进行了这种推断。
现在,当你有一个像Nothing
这样的数字文字时,推断它是3
类型,直到你真正将它提交给特定的数据类型(如Num s => s
或{{ 1}})。
因此,当它将这两个事实放在一起时,它假设如下:
Int
。
由于Double
没有实例,因此在有机会抱怨Num (Maybe t) => 3 :: Maybe t
毫无意义之前就抱怨了。
答案 1 :(得分:3)
您希望还有什么回报,只需a
?这不起作用,因为a
和Nothing
不是同一类型。函数的所有定义都必须返回相同的类型。 Nothing
和Just a
匹配,因为它们都是Maybe a
类型。
答案 2 :(得分:2)
在no just版本中,它要求树中的项目为Maybe a。
我不完全确定错误的原因是例如Num(也许是a)。如果您使用字符串而不是3,我认为错误更具启发性。
*Main> nodeAreSameNoJust (Node "arst" Empty Empty) (Node "arst" Empty Empty)
<interactive>:1:24:
Couldn't match expected type `Maybe a'
against inferred type `[Char]'
In the first argument of `Node', namely `"arst"'
In the first argument of `nodeAreSameNoJust', namely
`(Node "arst" Empty Empty)'
In the expression:
nodeAreSameNoJust
(Node "arst" Empty Empty) (Node "arst" Empty Empty)
这里更清楚的是,它期待类似于某种类型的东西。在这两种情况下,函数的第二种情况都是Nothing,因此结果类型被推断为Maybe a。通过包含Just,您在树中使用的值将被置于可能的类型中。如果没有这个,它期望结果a与Nothing的类型相同,因为函数的每个部分都需要是相同的类型。