There are a few ways to test values like this, but the way that’s most similar to what you’ve written is to use the extension called MultiWayIf
, available since GHC 7.6 (September 2012). Add the pragma:
{-# LANGUAGE MultiWayIf #-}
To the top of your source file (or use :set -XMultiWayIf
in GHCi) and you can write the following:
choice <- getLine
-- Simply add the ‘if’ keyword here.
if
| choice == "Computer" -> main
| choice == "2 Player" -> tictactoe
| otherwise -> putStrLn "That's not a choice!"
Ordinarily, guard syntax | condition
only works in two places: in definitions (where a guard goes after the name & arguments, before the =
symbol) and in case
(where it goes after the pattern, before the ->
symbol):
doubleIfEven :: Int -> Int
-- Definition
doubleIfEven x
| even x = x * 2
--------
| otherwise = x
-----------
doubleIfJustEven :: Maybe Int -> Maybe Int
doubleIfJustEven mx
-- Match
= case mx of
Just x
| even x -> Just (x * 2)
--------
| otherwise -> Just x
-----------
Nothing -> Nothing
Here are the alternatives:
case
expressions, in this case where you’re only testing for (structural) equality on strings:
case choice of
"Computer" -> main
"2 Player" -> tictactoe
_ -> putStrLn "That's not a choice!"
A local definition in a where
clause or let
binding:
tictac :: IO ()
tictac = do
putStrLn "Would you like to play against the computer or\
\ another player? Enter: 2 Player or Computer"
choice <- getLine
check choice
where
check choice
| choice == "Computer" = main
| choice == "2 Player" = tictactoe
| otherwise = putStrLn "That's not a choice!"
----
tictac :: IO ()
tictac = do
putStrLn "Would you like to play against the computer or\
\ another player? Enter: 2 Player or Computer"
let
check choice
| choice == "Computer" = main
| choice == "2 Player" = tictactoe
| otherwise = putStrLn "That's not a choice!"
choice <- getLine
check choice
Nested if
expressions:
if choice == "Computer" then main
else if choice == "2 Player" then tictactoe
else putStrLn "That's not a choice!"
case
with a dummy pattern and guards (an old idiom):
case () of
_ | choice == "Computer" -> main
| choice == "2 Player" -> tictactoe
| otherwise -> putStrLn "That's not a choice!"
#1 is most common for matching; #2 is used if you need guards and either want to avoid MultiWayIf
to support old compilers, or simply want to factor out the logic into a separate definition for readability; #3 and #4 aren’t very common or idiomatic, but there’s nothing “wrong” with them.