Проблема заключается в том, что статьи where
могут быть прикреплены только к привязкам, а не к выражениям. На самом деле:
main :: IO()
main = do
print $ result
where result = foldl' (+) 0 [1..1000000]
в точности эквивалентно:
main :: IO()
main = do
print $ result
where result = foldl' (+) 0 [1..1000000]
т.е. where
определяет локальные определения для main
не для print $ result
линии. Поскольку where
должен быть последней частью связывания, очевидно, следующее выражение print
вызывает синтаксическую ошибку.
Чтобы использовать where
внутри do
-блок вы должны использовать его при определении let
привязок, например, это (очень глупый пример):
main = do
let result = f
where f = foldl' (+) 0 [1..1000000]
print result
Вы можете проверить это в grammar:
decl → gendecl
| (funlhs | pat) rhs
rhs → = exp [where decls]
| gdrhs [where decls]
Обратите внимание, что where decls
является частью rhs
правила whic h определяет правую часть объявления. Если проверить правила exp
вы не найдете where
отметил:
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)
Кроме того, обратите внимание, что 'пусть decls в exp' * это * упоминалось, и может быть использован вместо, когда вам это нужно. –