I’ve found such code in the book “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
My question is: What job did the Just data constructor do? When I delete it, I will get error message such like
(in ghci)
......
<Main *> nodeAreSame (Node 3 Empty Empty) (Node 3 Empty Empty))
<interactive>:1:16:
No instance for (Num (Maybe a))
......
But when I try to compare the type difference between “Just” and “No Just” version:
nodeAreSameJust :: (Eq t) => Tree t -> Tree t -> Maybe t
nodeAreSameNoJust :: (Eq a) => Tree (Maybe a) -> Tree (Maybe a) -> Maybe a
So what is the key point here? Does it means when I put a var with type a in the node, the function will not output a node with type a, so it get an error?
In fact, the absence of
Justdoes not make it ill-typed.Here’s the deal. The code
nodeAreSame (Node a _ _) (Node b _ _) | a == b = a nodeAreSame _ _ = Nothingis well-typed provided that
aandbare of typeMaybe tfor somet, since that’s the type ofNothing. Thus the type system makes this inference.Now, when you have a numeric literal like
3, it is inferred to be of typeNum s => suntil you actually commit it to a particular data type (likeIntorDouble).So when it puts these two facts together, it presumes the following:
Num (Maybe t) => 3 :: Maybe t.As there is no instance for
Num (Maybe t), it complains at that point, before getting a chance to complain that3 :: Maybe tmakes no sense.