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有真正的变量.但默认情况下它不使用可变变量.
简单的答案是:是的,Haskell具有Haskell报告第3.2节中定义的变量.变量可以出现在图形并且因此可以绑定到一个值使用的构建体一样let,case和列表解析.
您的问题中可能隐含的是,如果变量是不可变的,那么变量是否被恰当地称为变量.我认为其他答案足以涵盖可变性.
是的,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)