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 Just
does not make it ill-typed.
Here's the deal. The code
nodeAreSame (Node a _ _) (Node b _ _)
| a == b = a
nodeAreSame _ _ = Nothing
is well-typed provided that a
and b
are of type Maybe t
for some t
, since that's the type of Nothing
. Thus the type system makes this inference.
Now, when you have a numeric literal like 3
, it is inferred to be of type Num s => s
until you actually commit it to a particular data type (like Int
or Double
).
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 that 3 :: Maybe t
makes no sense.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With