I've started to work through http://www.cs.nott.ac.uk/~pszgmh/monads for a intro on functional programming course. What better way to try and understand stuff than to actually try and test the code.
Alas, on the second page I encounter the following:
data Expr = Val Int | Div Expr Expr
eval :: Expr -> Int
eval (Val n) = n
eval (Div x y) = eval x `div` eval y
Which produces an error when I try to run it. I'm not quite sure why this happens. When I try
eval (Val 4) `div` eval (Val 2)
in the repl-loop, it works just fine, but
eval 4 `div` eval 2
Ends in a type inference error.
When I update my definition to the following:
data Expr = Val Int | Div Expr Expr
eval :: Expr -> Int
eval (Val n) = n
eval (Div x y) = eval (Val x) `div` eval (Val y)
I get a type error in definition. What is wrong with the first definition? The course uses Hugs by the way.
What eval
expects is an argument of a type that eval
is defined for. Looking at the signature, it requires an argument of type Expr
, either a Val
or a Div
. eval 4
means that you're passing an Int
to the function. For that to work, eval
would have to be defined as:
eval :: Int -> Int
By writing (Val 4)
, you are invoking one of the data constructors of Expr
type, creating a new value of type Expr
, which you can pass to eval
and make the compiler happy.