Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell - Use Just or no Just made difference, but I don't know why

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?

like image 891
snowmantw Avatar asked Dec 04 '22 12:12

snowmantw


1 Answers

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.

like image 191
intoverflow Avatar answered May 23 '23 14:05

intoverflow