[Haskell-beginners] if statements

Marc Weber marco-oweber at gmx.de
Sat Jan 23 13:27:17 EST 2010

Hi John,

You've several errors.
What is isDigit?

Let's start reading your code like the compiler does:

> evalStep (Add x y) = do
Fine Add x y thus both x and y are of type Expression
because the constructor Add has been defined this way:
>                 | Add Expression Expression

Now let's have a look at this line:
>   if x = isDigit

if x = isDigit

What is isDigit ?
Hoogle shows there is a isDigit function you didn't import.
It's type is
  isDigit :: Char -> Bool

So your if statement reads as
if x is a function ?
You can't compare a function with a value "x".

Anyway you want == not = to compare for equality.

At this point I stop parsing your code because it doesn't make sense at
all. You usually use pattern matching for this kind of stuff:

evalStep (Add x y) = case x of
  Val xval -> case y of 
    Val yval -> (evalStep xval) + (evalStep yval)
    _ -> error "don't know what to do"
  _ -> error "don't know what to do"

This is too verbose. It doesn't make sense to write it this way.

Let's do it right ( I feel like doing ones homework here...) but I don't
implement every case so I don't feel guilty :)

Step by step:

evalStep (Add x y) =
  let xEvaled = evalStep x
      yEvaled = evalStep y
  in Val (xEvaled + yEvaled)
evalStep( Multiply  a b) = error "TODO implement multiply"
evalStep _               = error "TODO (everything else I didn't match explicitely)"

shorter (that's what I would do:)

evalStep (Add x y) = Val $ (evalStep x) + (evalStep y)
or even shorter:
evalStep (Add x y) = Val $ evalStep `on` (+) x y
`on` applies a function to both operands before applying the operand.

Summary: Whenever you want to use if .. else or a switch .. case ..
thing remember that Haskell does have pattern matching and you should
use it.

Your isDigit function could be implemented using pattern matching (in
fact it's the only way I know about). It looks like this:

isDigit (Val _) = true -- Val is a digit
isDigit _ = false      -- everything else is not

Then you could use if isDigit val then .. else ..
but it still doesn't make much sense because you still have to get the
val out of the constructor.

if isDigit val then
  let Val x = val -- now you can use x (which is Int) to use primitive +/-* operations
  in x * 2
else ..

It doesn't hurt visiting the haskell.org page and reading some

Marc Weber

More information about the Beginners mailing list