以下代码无法解析:
main :: IO ()
main = do
print $ result
where result = foldl' (+) 0 [1..1000000]
print $ result
where result = last [1..1000000]
编译器在第二次印刷时抱怨: src / Main.hs:10:5:输入'print'
时解析错误为什么会这样?
答案 0 :(得分:9)
问题是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
规则的一部分,该规则定义了声明的右侧。如果您检查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)