为什么 `where` 在列表理解中产生解析错误,而 `let` 却没有?

Why `where` produces a parse error inside list comprehension, but `let` doesn't?

让我们定义一个名为 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只有在变量被描述后才被允许,因此在列表推导中是不正确的。