Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the following code not parse?

Tags:

haskell

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?

like image 451
yong Avatar asked Feb 02 '26 05:02

yong


1 Answers

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) 
like image 146
Bakuriu Avatar answered Feb 05 '26 01:02

Bakuriu



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!