Reputation: 6220
I'm starting to learn haskell and I'm solving some simple programming challenges. So my current problem right now is just printing some text based on the value being passed:
main = do
n <- readLn :: IO Int
if n `mod` 2 > 0
then putStrLn "Weird"
else if n > 1 && n < 6
then putStrLn "Not Weird"
else if n > 5 && n < 21
then putStrLn "Weird"
else putStrLn "Not Weird"
However I think this is fairly ugly, is there someway I could replace the nested if structure with a more elegant pattern matching?
I've tried:
main :: IO()
main = do
n <- readLn :: IO Int
case n of
n `mod` 2 /= 0 -> putStrLn "Weird"
n >= 2 && N <= 5 -> putStrLn "Not Weird"
n >= 6 && N <= 20 -> putStrLn "Weird"
n > 20 -> putStrLn "Not Weird"
but I get a compile error.
Edit: Final solution
check :: Int -> String
check n
| (n `mod` 2 /= 0) = "Weird"
| (n >= 2) && (n <= 5) = "Not Weird"
| (n >= 6) && (n <= 20) = "Weird"
| otherwise = "Not Weird"
main :: IO()
main = do
n <- readLn :: IO Int
putStrLn (check n)
Upvotes: 2
Views: 525
Reputation: 170723
"multiway if" was mentioned in chi's answer but not explained and I think it's useful to know about for such cases. Enabling the MultiWayIf
extension (e.g. by writing {-# LANGUAGE MultiWayIf #-}
at the top of the file) allows you to write
if | (n `mod` 2 /= 0) -> putStrLn "Weird"
| (n >= 2) && (n <= 5) -> putStrLn "Not Weird"
| (n >= 6) && (n <= 20) -> putStrLn "Weird"
| otherwise -> putStrLn "Not Weird"
Upvotes: 1
Reputation: 476567
A case
expression [Haskell-report] deals with patterns. An expression like n `mod` 2 /= 0
is not a pattern.
I propose to define a helper function, and use guards:
tmp :: Int -> String
tmp n | n `mod` 2 /= 0 = "Weird"
| n >= 2 && N <= 5 = "Not Weird"
| n >= 6 && N <= 20 = "Weird"
| n > 20 = "Not Weird"
| otherwise = …
You will still need to define a value for the otherwise
case, in case n <= 0
.
We can then use this with:
main = do
n <- readLn
putStrLn (tmp n)
Upvotes: 3
Reputation: 116139
You need to use guards if you have boolean expressions (conditions), instead of actual patterns.
main :: IO()
main = do
n <- readLn :: IO Int
case () of
_ | n `mod` 2 /= 0 -> putStrLn "Weird"
| n >= 2 && n <= 5 -> putStrLn "Not Weird"
| n >= 6 && n <= 20 -> putStrLn "Weird"
| n > 20 -> putStrLn "Not Weird"
Consider using otherwise
in the last case: assuming you want to catch everything else, it's faster and suppresses a GHC warning about non-exhaustiveness.
A "multiway if" can also be used as an alternative, but it requires an extension.
Upvotes: 5