让我们定义一个名为func
的简单函数:
func :: [Int] -> [Int]
在定义这个虚假函数时,我想在列表理解中使用 where
子句。
func xs = [ y where y = x + 1 | x <- xs]
不幸的是,在尝试编译时,我收到以下消息:
parse error on input `where'
如果我决定使用 let
子句,一切正常:
func xs = [ let y = x + 1 in x | x <- xs] -- compilation successful
为什么我不能像我最初打算的那样使用where
?
正如你在Haskell报告(https://www.haskell.org/onlinereport/exps.html#list-comprehensions)列表中看到的那样,推导式在左侧采用一个表达式。 let
是一个表达式,而where
是顶级声明的一部分。因此,那里是不允许的。
这是因为列表推导式等同于do
语法。
需要明确的是,这:
[f a b q | a <- as, b <- bs, let q = a + b]
相当于:
do a <- as
b <- bs
let q = a + b
return (f a b q)
并且let
表达式允许在do
块中使用。
至于为什么不允许使用where
子句,它们的目的是在顶级声明中提供一个临时范围。
即:
binding = la da fu gu
where la a b c = c a b
da = 6
...
换句话说,只有在描述变量之后才允许where
,因此在列表推导中是不正确的。