I have entered some code in ghci
, similar to this:
main = do { a <- getLine ; let b = "Hello " ++ a ; putStrLn b }
However, I get this error:
<interactive>:1:63: error: parse error on input `}'
In previous versions of Haskell/GHC, I remember this working just fine - it was even explicitly said that, in do
blocks, you don't need the in
keyword. Yet, the only way to get this to work seems to be:
main = do { a <- getLine ; let b = "Hello " ++ a in putStrLn b }
which doesn't produce this error.
Has this been removed? If so, do I need a second do
block inside the let in
expression?
let
is a layout keyword like do
, both as a statement in a do
block and in a let
…in
… expression, because it introduces a block of bindings. This:
main = do
a <- getLine
let b = "Hello " ++ a
putStrLn b
Desugars to this:
main = do {
a <- getLine;
let {
b = "Hello " ++ a;
};
putStrLn b;
};
Whereas what you’ve written is equivalent to this:
main = do {
a <- getLine;
let {
b = "Hello " ++ a;
putStrLn b
};
};
So naturally GHC is expecting something else—a pattern or =
—after putStrLn b
, since you could be defining a local function named putStrLn
with a parameter named b
. The solution is either to use explicit braces in the let
statement:
main = do { a <- getLine; let { b = "Hello " ++ a }; putStrLn b }
Or to use multiline mode in GHCi, either with the :{
command, terminated with the :}
command:
> :{
| main = do
| a <- getLine
| let b = "Hello " ++ a
| putStrLn b
| :}
>
Or with :set +m
, and terminated with a blank line:
> :set +m
| main = do
| a <- getLine
| let b = "Hello " ++ a
| putStrLn b
|
>
Followed by :unset +m
to return to single-line mode.