Haskell有变量吗?

Cur*_*son 31 variables monads haskell immutability referential-transparency

我经常听说Haskell没有变量的说法; 特别是,这个答案声称它没有,它至少被投票了九次并被接受.

那么它是否有变量,为什么?

这个问题似乎也适用于ML,F#,OCaml,Erlang,Oz,Lava和所有SSA中间语言.

Don*_*art 51

Haskell默认具有不可变变量(数学意义上的变量):

 foo x y = x + y * 2
Run Code Online (Sandbox Code Playgroud)

默认情况下,变量不是可变单元格.

Haskell也有可变的单元格,但你明确地启用它们:

 > import Data.IORef (newIORef, readIORef, writeIORef)
 > v <- newIORef 0
 > readIORef v
 0

 > writeIORef v 7
 > readIORef v
 7
Run Code Online (Sandbox Code Playgroud)

所以,YES Haskell有真正的变量.但默认情况下它不使用可变变量.


Chr*_*way 9

简单的答案是:是的,Haskell具有Haskell报告第3.2节中定义的变量.变量可以出现在图形并且因此可以绑定到一个值使用的构建体一样let,case和列表解析.

您的问题中可能隐含的是,如果变量是不可变的,那么变量是否被恰当地称为变量.我认为其他答案足以涵盖可变性.


Cur*_*son 5

是的,Haskell有变量.考虑(基本上等效的)定义

inc n = n + 1
inc = \n -> n + 1
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,n都是变量; 它会在不同的时间呈现不同的价值观.在Haskell的报告,在第3节是指这些明确的变量.

n这里是一个变量可以更容易地看到,如果我们考虑下面的完整的程序:

inc n = n + 1
f = inc 0
g = inc 1
main = print (f+g)
Run Code Online (Sandbox Code Playgroud)

当然,打印的答案是"3".在评估时f,当我们展开时inc x将采用该值0,并且当稍后(或更早!)评估时g,当我们展开时inc x将采用该值1.

可能会出现一些混淆,因为Haskell与问题中列出的其他语言一样,是一种单任务语言:它不允许在范围内重新分配变量.一旦n被分配了值42,它就不能是42而不是引入一个新的范围与新的范围n(这是一个不同的变量,遮蔽另一个n)绑定到另一个值.

在某些情况下,这可能并不完全明显,例如表达式使用do:

 do let n = 1
    print n
    let n = 2
    print n
Run Code Online (Sandbox Code Playgroud)

但是如果删除语法糖,将其转换为没有的Haskell do,就会发现创建了一个新的嵌套作用域,其中n内部作用域是一个不同的变量,它遮蔽n了外部作用域:

(let n = 1 
  in (print n >> (let n = 2
                   in print n)))
Run Code Online (Sandbox Code Playgroud)

  • Dario,维基百科不同意,列出了九种语言,其中所有变量都是单一赋值,另外五种是单一赋值是一种选项:http://en.wikipedia.org/wiki/Single_assignment.此外,提出该术语的数学家也在单指派意义上使用变量.如果你要反对这个,那么如何发布一个详细的答案来说明为什么这是一个错误的观点? (7认同)
  • Haskell 中没有变量!变量可以重新分配。您在函数或 let-bindings 中拥有的只是一个不可变的函数参数,一个绑定到名称的值! (2认同)