I tried to rewrite that program, which is working:
nameIOite :: IO ()
nameIOite = do
putStrLn "What's your name ?"
name <- getLine
if name `elem` ["Simon","John","Phil"]
--if name == "Simon" || name == "John" || name == "Phil" also works but is ugly.
then putStrLn "I think Haskell is a great programming language."
else if name == "Koen"
then putStrLn "I think debugging Haskell is fun."
else putStrLn "I don't know your name."
This is done using if/then/else (therefore the suffix ite in nameIOite
)
Then I'vs tried using guards:
nameIOg :: IO ()
nameIOg = do
putStrLn "What's your name ?"
name <- getLine
let answer
| name `elem` ["Simon","John","Phil"] = "I think Haskell is a great programming language."
| name == "Koen" = "I think debugging Haskell is fun."
| otherwise = "I don't know your name."
putStrLn answer
This didn't work:
test.hs:6:9: error:
parse error (possibly incorrect indentation or mismatched brackets)
|
6 | | name `elem` ["Simon","John","Phil"] = "I think Haskell is a great programming language."
| ^
Failed, no modules loaded.
After some experimenting, the solution turned out to indent the guards once more (which isn't clear to me at all):
nameIOg :: IO ()
nameIOg = do
putStrLn "What's your name ?"
name <- getLine
let answer
| name `elem` ["Simon","John","Phil"] = "I think Haskell is a great programming language."
| name == "Koen" = "I think debugging Haskell is fun."
| otherwise = "I don't know your name."
putStrLn answer
Ok, one module loaded.
Where does that double indentation come from and is there a way to write this more elegently ?
(By the way, I stumbled across this when reviewing my wikibook.hs files.)
Source of example: there
Solutions: there
let
allows multiple definitions, as in
main = do
doSomething
let x = 1
y = 2
z = 3
print (x+y+z)
Note the indentation. y = 2
is not parsed to continue the definition x = 1
since it starts on the same column.
If you want a new line to be parsed as if it continued the previous line, you have to indent it more. E.g.
main = do
doSomething
let x | someCondition = 1
| otherwise = 0 -- more indented
y = 2
z = 3
print (x+y+z)
or, using another line
main = do
doSomething
let x
| someCondition = 1 -- more indented
| otherwise = 0 -- more indented
y = 2
z = 3
print (x+y+z)
Indentation rules might seem puzzling at first, but they are actually quite simple.
I think your current code is as elegant as it might be -- it looks fine to me.
If you want more alternatives, you could use if then else
, even if most Haskellers would prefer guards. (Personally, I don't have a real preference)
main = do
doSomething
let x = if condition then 1
else if someOtherCondition then 0
else -1
y = 2
z = 3
print (x+y+z)
You could also use another line, e.g. (I'd tend to prefer that)
main = do
doSomething
let x =
if condition then 1
else if someOtherCondition then 0
else -1
y = 2
z = 3
print (x+y+z)
or even
main = do
doSomething
let x =
if condition
then 1
else if someOtherCondition
then 0
else -1
y = 2
z = 3
print (x+y+z)
I'm not claiming a style is overwhelmingly better than another one.