Haskell - syntax in do blocks (using IO)
-
12-04-2021 - |
Question
The compiler says
The last statement in a 'do' construct must be an expression:
rmax <- getInteger
when attempting to load a file containing the following snippets of code:
getInteger :: IO Integer
getInteger = readLn
main :: IO ()
main = do
putStrLn "specify upper limit of results"
rmax <- getInteger
if rmax `notElem` mot
then do putStrLn "run again and enter a multiple of 10"
else do print pAllSorted
What does it (the compiler message) mean, and why does it occur here? (whereas it doesn't in:)
main = do
line <- getLine
if null line
then return ()
else do
putStrLn $ reverseWords line
main
reverseWords :: String -> String
reverseWords = unwords . map reverse . words
(above example taken from http://learnyouahaskell.com/input-and-output)
Solution
Your indentation is probably messed up because of mixed tabs and spaces. In fact, there appears to be a stray tab in the code snippet in your question, which I'm assuming you pasted directly from your source file.
Most likely, GHC is interpreting the tabs differently from how your editor displays them, so it thinks the do
block ends after the line in question.
As a rule of thumb, it's best to use only spaces in Haskell. The language defines very specific rules for interpreting tabs that most code editors don't agree with, but spaces are unambiguous and consistent.