Diyor Ismatullaev
Diyor Ismatullaev

Reputation: 61

Haskell: Multi-way if-expressions need MultiWayIf turned on

Trying to build with "stack build":

module Main where


analyzeGold :: Int -> String
analyzeGold standard =
  if | standard == 999 -> "Wow! 999 standard!"
     | standard == 750 -> "Great! 750 standard."
     | standard == 585 -> "Not bad! 585 standard."
     | otherwise -> "I don't know such a standard..."

main :: IO ()
main = do
  putStrLn (analyzeGold 999)

And I got:

    Multi-way if-expressions need MultiWayIf turned on
  |
6 |   if | standard == 999 -> "Wow! 999 standard!"
  |   ^^

How to fix it?

stack 1.7.1, GHC 8.2.2

Upvotes: 3

Views: 4295

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476557

Well in Haskell there is only an if-then-else clause. If you want these "multi-if" statements, you use a guard.

Using guards

Your syntax is already rather close to a guard, except that it does not have an if keyword, and that the equality sign (=) is used to denote what the output is in that case.

So you should rewrite it to:

analyzeGold :: Int -> String
analyzeGold standard
    | standard == 999 = "Wow! 999 standard!"
    | standard == 750 = "Great! 750 standard."
    | standard == 585 = "Not bad! 585 standard."
    | otherwise = "I don't know such a standard..."

See here [lyah] for some information about the syntax and use of guards.

Using patterns

Since your checks each time check equality of integer literals, we can actually move the checks from the guards to the patterns, like:

analyzeGold :: Int -> String
analyzeGold 999 = "Wow! 999 standard!"
analyzeGold 750 = "Great! 750 standard."
analyzeGold 585 = "Not bad! 585 standard."
analyzeGold _ = "I don't know such a standard..."

Here the underscore (_) acts as a wildcard that matches all values (well all patterns that are not matched by earlier clauses).

Using the MultiWayIf extension

You can also enable a GHCi extension to enable this extension, by writing a pragma in the head of the file, or by using -XMultiWayIf when invoking the interpreter. So:

{-# LANGUAGE MultiWayIf #-}

analyzeGold :: Int -> String
analyzeGold standard =
    if | standard == 999 -> "Wow! 999 standard!"
       | standard == 750 -> "Great! 750 standard."
       | standard == 585 -> "Not bad! 585 standard."
       | otherwise -> "I don't know such a standard..."

Or:

$ ghci -XMultiWayIf
GHCi, version 8.0.2: http://www.haskell.org/ghc/  :? for help
Prelude> :{
Prelude| analyzeGold :: Int -> String
Prelude| analyzeGold standard =
Prelude|     if | standard == 999 -> "Wow! 999 standard!"
Prelude|        | standard == 750 -> "Great! 750 standard."
Prelude|        | standard == 585 -> "Not bad! 585 standard."
Prelude|        | otherwise -> "I don't know such a standard..."
Prelude| :}

Upvotes: 18

Related Questions