列表推导中的变量是不可变的吗?

fly*_*sch 4 haskell

列表推导中的变量是不可变的吗?

[x + 1 | x <- [1,2,3,4,5]]
Run Code Online (Sandbox Code Playgroud)

例如,在上面的例子中,x似乎改变了它的价值.这是真正发生的事情,还是在这里工作更复杂?

bhe*_*ilr 9

Haskell中没有变量,只有绑定到名称的值.

像这样的列表理解将变成什么实际上是monadic列表代码:

y = [x + 1 | x <- [1, 2, 3, 4, 5]]
y = do
    x <- [1, 2, 3, 4, 5]
    return (x + 1)
Run Code Online (Sandbox Code Playgroud)

然后这进一步减少到使用>>=:

y = [1, 2, 3, 4, 5] >>= (\x -> return (x + 1))
Run Code Online (Sandbox Code Playgroud)

然后我们可以查看Monad实例的定义[]:

instance Monad [] where
    return x = [x]
    list >>= f = concat (map f list)
    -- uses the `concatMap` function in the actual definition
    -- where `concatMap f list = concat (map f list)`
Run Code Online (Sandbox Code Playgroud)

所以更换return:

y = [1, 2, 3, 4, 5] >>= (\x -> [x + 1])
Run Code Online (Sandbox Code Playgroud)

然后>>=:

y = concat (map (\x -> [x + 1]) [1, 2, 3, 4, 5])
Run Code Online (Sandbox Code Playgroud)

现在我们可以减少它:

y = concat [[1 + 1], [2 + 1], [3 + 1], [4 + 1], [5 + 1]]
y = concat [[2], [3], [4], [5], [6]]
y = [2, 3, 4, 5, 6]
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,它不是x一个更改值的变量,而是x一个lambda函数的参数,然后映射到目标列表.

  • 优秀的答案,但两个挑剔:(a)"与名称绑定的价值"是数学中的变量; 说Haskell没有变数我认为只会造成混乱; (b)据我了解,编译器实际上并未将列表推导转换为monadic代码; 基本上,它会跳过你的答案中涉及`do`,`>> =`和`return`的步骤.这完全等同于你展示的内容. (2认同)