i try to become familiar with the if-condition statements in haskell

assume that i´ve an argument x and i try the following in haskell

functionname x = if x > 0 then x-5
                          if x-5 == 0 then 1
                          else if x-5 /= 0 then functionname x-5
                          else if x-5 <  then 0

so, the idea was to subtract 5 from x, check if the result is 0, if yes, then give a 1. If not then invoke the function again with the expression x-5. If the result of x-5 is negative then give a 0.

so, my questions: Would that be correct? Because when i try that, i´ve got a message like parse error on input 'functionname'.

how can i fix that problem? Are the if-else conditions wrong ?


programm :: Int -> Bool

programm x |  x > 0 =
   if z == 0 then True
   else if z < 0 then False
   else programm z
   where
   z = z-2

programm x |  x < 0 =
   if z == 0 then True
   else if z > 0 then False
   else programm z
   where
   z = z+2

so, i wanted to have the possibility to decide of a given number is even. So, i modify your solution a little bit. its the same but, at the beginning of the two declarations i said : x > 0 = .... and x < 0 =... Because i want to say that for example -4 is also even. for that reason: the first declarations should handle the positive even numbers and the second declarations handles the negative even numbers.

when i give that to the compiler, then the message : Exception appears. Where i ve made the mistake?

2 upvote
  flag
Unlike in some other languages, every if in Haskell needs an else. – n.m.

3 Answers 11

Use guards to make things clear:

functionname x
  | x > 0      = x - 5
  | x - 5 == 0 = 1
  | x - 5 /= 0 = functionname (x - 5)
  | x - 5 < 0  = 0
upvote
  flag
Thanks for your answer. But when i do that, then the compiler complain that the result from the first line (| x > 0 = x - 5) should be a boolean. – user3097712
3 upvote
  flag
@user3097712 where? ideone.com/hXdWDn – n.m.

Every if needs to have an else clause associated with it.

The very first one doesn't and the very last one doesn't either. This works just fine:

functionname x = if x > 0 then x-5
                 else if x-5 == 0 then 1
                 else if x-5 /= 0 then functionname x-5
                 else if x-5 < 0 then 0 else 1
upvote
  flag
Thanks for your answer. But when i do that, then the compiler complain that the result from the first line (| x > 0 = x - 5) should be a boolean. – user3097712

so, the idea was to subtract 5 from x, check if the result is 0, if yes, then give a 1. If not then invoke the function again with the expression x-5. If the result of x-5 is negative then give a 0.

That might be written like this:

functionname x =
    if x' == 0 then 1
    else if x' < 0 then 0
    else functionname x'
    where
    x' = x - 5

Here, I use a where clause to locally define x' as x - 5 and then use it for the tests and the recursive call. Your first branch, if x > 0 then x-5, does not appear in your description of what function should do (it gives x - 5 results as result whenever x is larger than zero, which is probably not what you want). Also, note that every if needs an else as well as a then.

so, i wanted to have the possibility to decide of a given number is even. So, i modify your solution a little bit. its the same but, at the beginning of the two declarations i said : x > 0 = .... and x < 0 =... Because i want to say that for example -4 is also even. for that reason: the first declarations should handle the positive even numbers and the second declarations handles the negative even numbers.

First of all, in the second version of your function the definition in the where clause should be z = x + 2, as z = z + 2 will not terminate. This being an evenness test, you also want to perform the tests on x rather than z. With that fixed, your solution with nested conditionals should work fine (note, however, that you are not treating the x == 0 case; the first guard should be x >= 0). There is a more elegant way of writing the function, though:

myEven :: Int -> Bool
myEven x = myEven' (abs x)
    where
    myEven' x
        | x == 0    = True
        | x < 0     = False
        | otherwise = myEven' (x - 2)

abs is the familiar absolute value function, while myEven' amounts to the x > 0 branch of your original definition. Taking the absolute value of x is the easiest way to avoid writing two nearly equal branches to handle the negative and non-negative cases.

N.B.: While this is probably just a learning exercise, if you ever need to find whether a number is even there is an even function available from the Prelude. There is also mod if you need to test divisibility for other numbers.

upvote
  flag
@user3097712 I updated the answer to match the edited question. – duplode

Not the answer you're looking for? Browse other questions tagged or ask your own question.