Bob Bobington
Bob Bobington

Reputation: 309

Correct syntax for if statements in Haskell

The only input you need is the grade number that you get. This is what I have so far.

myScore x = if x > 90
    then let x = "You got a A"
if 80 < x < 90 
    then let x = "you got a B"
if 70 < x < 80
    then let x = "You got a C"
if 60 < x < 90
    then let x = "you got a D"
else let x = "You got a F"

This gives me an error "parse error on input `if' ", I also tried:

myScore x = (if x > 90 then "You got an A" | if 80 < x < 90 then "You got a B" | if 70 < x < 80 then "You got a D" | if 60 < x < 70 then "You got a D"  else "You got a F")

but that didn't work either.

Upvotes: 23

Views: 115813

Answers (4)

Code-Apprentice
Code-Apprentice

Reputation: 83577

You need to add else before each if. Recall that in Haskell, every expression must evaluate to a value. This means that every if expression must have a matching then clause and a matching else clause. Your code only has one else with four ifs. The compiler complains because of the missing elses. When you fix it, your Haskell code will look a lot like a if...else if...else chain from other programming languages.

Upvotes: 7

Peter Hall
Peter Hall

Reputation: 58855

You can't have the let inside the conditionals, otherwise the variable x won't be available in the following expression that needs it.

In your case, you don't even need the let-binding because you just want to return the string immediately, so you can just do:

myScore x = 
    if x > 90 then "You got a A"
    else if 80 < x && x < 90 then "you got a B"
    else if 70 < x && x < 80 then "You got a C"
    else if 60 < x && x < 70 then "you got a D"
    else "You got a F"

Also note, you can't do 80<x<90 - you have to combine two expressions with the && operator..

The above can be further simplified syntactically, using guards:

myScore x
    | x > 90 = "You got a A"
    | x > 80 = "you got a B"
    | x > 70 = "You got a C"
    | x > 60 = "you got a D"
    | otherwise = "You got a F"

Upvotes: 44

Ingo
Ingo

Reputation: 36339

For completeness, here the guard syntax suggested by @hammar:

myScore x
   | x > 90 = "A"
   | x > 80 = "B"
   | x > 70 = "C"
   | x > 60 = "D"
   | otherwise = "F"

(How about "E"?)

Note that it is not needed to check x > 80 && x < 90 here, because when it passes the first guard, it must be that x <= 90. And so for all the following guards: all preceding guards are guaranteed to be false, whenever a guard is tried.

This also corrects the logical error to score an 'F' if x == 90.

Upvotes: 3

amindfv
amindfv

Reputation: 8448

Defining x won't define it out of its lexical scope -- in this case, x won't be accessible to anything. Instead, use the syntax

let x = 
      if 5 < 4
      then "Hmm"
      else "Better"
in "Here's what x is: " ++ x

Also, using all of those ifs is not the best way in Haskell. Instead, you can use the guard syntax:

insideText x
   | elem x [2,3,7] = "Best"
   | elem x [8,9,0] = "Better"
   | otherwise      = "Ok." 

Upvotes: 2

Related Questions