The following code does not parse:
main :: IO ()
main = do
print $ result
where result = foldl' (+) 0 [1..1000000]
print $ result
where result = last [1..1000000]
The compiler complains on the second print: src/Main.hs:10:5: parse error on input `print'
Why is this?
The problem is that where clauses can be attached to bindings only, not to expressions.
In fact:
main :: IO ()
main = do
print $ result
where result = foldl' (+) 0 [1..1000000]
is exactly equivalent to:
main :: IO ()
main = do
print $ result
where result = foldl' (+) 0 [1..1000000]
i.e. the where defines local definitions for main not for the print $ result line.
Since where must be the last part of a binding obviously the following print expression causes a syntax error.
To use a where inside a do-block you have to use it when defining the let bindings such as this (very silly example):
main = do
let result = f
where f = foldl' (+) 0 [1..1000000]
print result
You can check this in the grammar:
decl → gendecl
| (funlhs | pat) rhs
rhs → = exp [where decls]
| gdrhs [where decls]
Note that the where decls is part of the rhs rule which defines the right hand side of a declaration. If you check the rules for exp you wont find where mentioned:
exp → infixexp :: [context =>] type (expression type signature)
| infixexp
infixexp → lexp qop infixexp (infix operator application)
| - infixexp (prefix negation)
| lexp
lexp → \ apat1 … apatn -> exp (lambda abstraction, n ≥ 1)
| let decls in exp (let expression)
| if exp [;] then exp [;] else exp (conditional)
| case exp of { alts } (case expression)
| do { stmts } (do expression)
| fexp
fexp → [fexp] aexp (function application)
aexp → qvar (variable)
| gcon (general constructor)
| literal
| ( exp ) (parenthesized expression)
| ( exp1 , … , expk ) (tuple, k ≥ 2)
| [ exp1 , … , expk ] (list, k ≥ 1)
| [ exp1 [, exp2] .. [exp3] ] (arithmetic sequence)
| [ exp | qual1 , … , qualn ] (list comprehension, n ≥ 1)
| ( infixexp qop ) (left section)
| ( qop⟨-⟩ infixexp ) (right section)
| qcon { fbind1 , … , fbindn } (labeled construction, n ≥ 0)
| aexp⟨qcon⟩ { fbind1 , … , fbindn } (labeled update, n ≥ 1)
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