4

我在“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

那么这里的关键点是什么?这是否意味着当我在节点中放置一个带有 type 的 var 时a,该函数不会输出一个带有 type 的节点a,所以会出错?

4

3 回答 3

12

实际上,缺少Just不会使其类型错误。

这是交易。编码

nodeAreSame (Node a _ _) (Node b _ _)
            | a == b = a
nodeAreSame _ _ = Nothing

良好类型的,a并且bMaybe tsome的类型t,因为那是Nothing. 因此,类型系统做出了这种推断。

现在,当您有一个数字文字时3,它会被推断为类型Num s => s,直到您实际将其提交给特定的数据类型(如Intor Double)。

因此,当将这两个事实放在一起时,它假定以下内容:

Num (Maybe t) => 3 :: Maybe t.

由于没有 的实例Num (Maybe t),它会在那时抱怨,然后才有机会抱怨3 :: Maybe t没有意义。

于 2010-07-16T05:00:10.643 回答
3

简单地说,您还期望返回a什么?那是行不通的,因为aandNothing不是同一类型。函数的所有定义都必须返回相同的类型。 NothingJust a匹配,因为它们都是 type Maybe a

于 2010-07-16T04:29:23.810 回答
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)

这里更清楚的是它期待的是 Maybe a 类型的东西。在这两种情况下,函数的第二种情况都是Nothing,所以结果类型被推断为Maybe a。通过包含 Just,您在树中使用的值会被放入可能的类型。没有这个,它期望得到的 a 与 Nothing 的类型相同,因为函数的每个部分都需要是相同的类型。

于 2010-07-16T04:30:17.473 回答