I'm running GHC version 7.8.3 on Windows 7.
Ok, this is not about fancy code snippets. I'm just trying not be a noob here and actually compile something in a way that vaguely resembles the structure of side-effect languages.
I have the following code:
main =
do {
let x = [0..10];
print x
}
I've learned here, that the keyword do is a fancy syntactic sugar for fancy monadic expressions. When I try to compile it, I get the following error:
main.hs:4:1: parse error on input 'print'
And I've learned in this other question, that tabs in Haskell are evil, so I've tried to omit them:
main =
do {
let x = [0..10];
print x
}
And I've failed miserably, because the parse error persists.
I've also learned here, that print is a syntactic sugar for the fancy equivalent:
main =
do {
let x = [0..10];
putStrLn $ show x
}
But then I get this error instead:
main.hs:4:9: parse error on input 'putStrLn'
Trying to face my despair, I've tried to omit the let keyword, after reading this answer:
main =
do {
x = [0..10];
print x
}
And then I get:
main.hs:4:1: parse error on input '='
And in a final useless attempt, I've even tried to omit the ';' like this:
main =
do {
let x = [0..10]
print x
}
And got:
main.hs:4:1: parse error on input 'print'
So,
How to properly use monadic expressions in Haskell without getting parse errors? Is there any hope?
It took me a while to see what was actually going on here:
main =
do {
let x = [0..10];
print x
}
The above looks as if we have a do
with two statements, which is perfectly fine. Sure, it is not common practice to use explicit braces-and-semicolons when indentation implicitly inserts them. But they shouldn't hurt... why then the above fails parsing?
The real issue is that let
opens a new block! The let
block has no braces, so the indentation rule applies. The block starts with the definition x = [0..10]
. Then a semicolon is found, which promises that another definition is following e.g.
let x = [0..10] ; y = ...
or even
let x = [0..10] ;
y = ... -- must be indented as the x above, or more indented
However, after the semicolon we find print
, which is even indented less than x
. According to the indentation rule, this is equivalent to inserting braces like:
main =
do {
let { x = [0..10]; }
print x
}
but the above does not parse. The error message does not refer to the implicitly inserted braces (which would be very confusing!), but only to the next line (nearly as confusing in this case, unfortunately).
The code can be fixed by e.g. providing explicit braces for let
:
main = do { let { x = [0..10] };
print x }
Above, indentation is completely irrelevant: you can add line breaks and/or spaces without affecting the parsing (e.g. as in Java, C, etc.). Alternatively, we can move the semicolon below:
main = do { let x = [0..10]
; print x }
The above semicolon is on the next line and is less indented than x
, implicitly inserting a }
which closes the let
block. Here indentation matters, since let
uses the indentation rule. If we indent the semicolon more, we can cause the same parse error we found earlier.
Of course, the most idiomatic choice is using the indentation rule for the whole code:
main = do let x = [0..10]
print x
I was about to say, with no useful information, that
main = do
let x = [0..10]
print x
Was working for me, but I'm now off to read about the in
within the braces.
As a slight aside, I found http://echo.rsmw.net/n00bfaq.html quite handy for reading about identation/formatting.
main = do let x = [0..10]
print x
works for me
and so does
main = do { let x = [0..10]
in print x }
I think you're trying to mix some different syntax options up.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With