在 Haskell 中,可变性是否总是必须反映在类型系统中?
我是 Haskell 的新手,所以如果这个问题很愚蠢,请原谅。
想象一下,我们有两个绑定到名称 x 和 y 的数据结构。
x 是可变的。
y 不是。
作为一个问题或原则,x 是否一定具有与 y 不同的类型?
I'm new to Haskell, so please forgive if this question is dumb.
Imagine that we have two data structures bound to the names x and y.
x is mutable.
y is not.
As a matter or principle, does x necessarily have a different type than y?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
简短的回答:是的。
在 Haskell 中,所有变量在技术上都是不可变的。与 JavaScript 不同,一旦你在 Haskell 中定义了一个新变量并将其绑定到一个初始值:
这就是它永远的值。在
body1
中使用x
的任何地方,其值都保证是expression1
的(固定)值。 (嗯,从技术上讲,您可以在body1
中定义一个具有相同名称的全新不可变变量x
,然后在 body 中定义一些x
可能会引用那个新变量,但那是完全不同的事情。)Haskell 确实有可变的数据结构。我们通过创建一个新的可变结构并将其绑定到一个不可变变量来使用它们:
这里,
xref
本身的值不是整数 15。相反,xref
被分配了一个不可变的、不可显示的值,该值标识一个“容器”,其内容当前为 15。要使用这个容器,我们需要显式地从中取出值,我们可以将其分配给不可变的变量:并显式地放置值进入it:
显然,关于这些值,以及通常需要通过 IO 或其他 monad 中的 monadic 操作访问它们的方式,还有很多可说的。
但是,即使抛开这一点,应该清楚的是,整数
15
和“内容初始化为整数15
的容器”是具有必然不同类型的对象。在本例中,类型分别为Int
和IORef Int
。因此,数据结构的可变性必然会反映在类型级别,仅仅因为 Haskell 中的可变性是通过这些类型的“容器”实现的,并且值的类型与值的类型不同。包含该值的容器。
Short answer: yes.
In Haskell, all variables are technically immutable. Unlike in, say, JavaScript, once you've defined a new variable in Haskell and bound it to an initial value:
that's its value forever. Everywhere that
x
is used inbody1
, its value is guaranteed to be the (fixed) value ofexpression1
. (Well, technically, you can define a brand new immutable variablex
with the same name inbody1
and then some of thex
s in body might refer to that new variable, but that's a whole different matter.)Haskell does have mutable data structures. We use them by creating a new mutable structure and binding that to an immutable variable:
Here, the value of
xref
itself is not the integer 15. Rather,xref
is assigned an immutable, undisplayable value that identifies a "container" whose contents are currently 15. To use this container, we need to explicitly pull values out of it, which we can assign to immutable variables:and explicitly put values into it:
There's obviously much more that can be said about these values, and the way in which they generally need to be accessed via monadic operations in
IO
or another monad.But, even setting that aside, it should be clear that the integer
15
and a "container whose contents are initialized to the integer15
" are objects with necessarily different types. In this case, the types areInt
andIORef Int
respectively.So, the mutability of data structures will necessarily be reflected at the type level, simply by virtue of the fact that mutability in Haskell is implemented via these sorts of "containers", and the type of a value is not the same as the type of a container containing that value.