Haskell:什么是不可变数据?

3

在大多数关于Haskell的文章中,你会发现类似“Haskell中的数据是不可变的”这样的说法。我不太明白为什么会这样。例如:

let a = 123
let a = 456

在主方法中运行。我只是将a的数据从123改为456。我错过了什么?这可能是我思路上的一个愚蠢错误 :/ 祝您拥有美好的一天!

8
你没有改变 a 的值,而是创建了一个同名的新对象。在编译时,最后出现的名称被选中。 - Ry-
1
好的。那么我猜,类似 let a = 3(换行)a = a *2 这样的写法是不被允许的? - jdstaerk
1
好的。你的例子就像执行 let b = a * 2。(当然,这对某些目的来说是可以正常工作的。) - Ry-
好的,谢谢你的回答,我明白了! - jdstaerk
2
你不应该把它看作是最后一个,而应该看作是最内层的。let a = a * 2 是完全合法的,但不会产生你期望的效果。试一试吧! - dfeuer
在GHCi中,a <- return (a*2)在提示符下也是合法的,并且确实会执行预期的操作。或者看起来像它正在做的那样。 :) - Will Ness
1个回答

18

实际上,a 没有改变。在 ghci 中尝试一下就可以看到:

> a = 123
> action = print a
> a = 456
> action
123

与具有可变变量的语言(例如Python)进行比较:

>>> a = 123
>>> def action(): print a
... 
>>> a = 456
>>> action()
456

谢谢!开始学习函数式编程似乎并不像面向对象编程那么容易 :D - jdstaerk
5
这是关于大脑“印记”的问题。如果一个人首先接触到纯函数式编程,面向对象编程可能会显得更加困难。 - chi
2
@DDerTyp,我想指出,上述在Haskell中非常不常见,以防这个答案让你认为使用不可变性是这样工作的。我们几乎从不以这种方式在重叠的范围内调用两个具有相同名称的东西。 - luqui
@luqui 是真的,除非在GHCi/IHaskell中摆弄。在那里,我经常“覆盖”变量。但是旧的、被遮蔽的值不会被理解为程序流的一部分,而仅仅是相同值的过时/错误实现。 - leftaroundabout

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接