在 Haskell 中,可变性是否总是必须反映在类型系统中?

Jam*_*ter 3 haskell type-theory immutability ghc mutability

我是 Haskell 的新手,所以如果这个问题很愚蠢,请原谅。

想象一下,我们有两个绑定到名称xy 的数据结构。

x是可变的。

y不是。

作为一个问题或原则,x是否一定具有与y不同的类型?

K. *_*uhr 5

简短的回答:是的。

在 Haskell 中,所有变量在技术上都是不可变的。与 JavaScript 不同,一旦你在 Haskell 中定义了一个新变量并将其绑定到一个初始值:

let x = expression1 in body1
Run Code Online (Sandbox Code Playgroud)

这就是它永远的价值。x在 中使用的任何地方body1,其值都保证是 的(固定)值expression1x(好吧,从技术上讲,您可以在 中 定义一个具有相同名称的全新不可变变量body1,然后xbody 中的某些 s 可能会引用该新变量,但这是完全不同的事情。)

Haskell 确实有可变的数据结构。我们通过创建一个新的可变结构并将其绑定到一个不可变变量来使用它们:

do ...
   xref <- newIORef (15 :: Int) 
   ...
Run Code Online (Sandbox Code Playgroud)

xref 这里,它本身的值不是整数 15。相反,xref它被分配了一个不可变的、不可显示的值,该值标识一个内容当前为 15 的“容器”。要使用这个容器,我们需要显式地从中提取值,我们可以分配给不可变变量:

  value_of_x_right_now <- readIORef xref
Run Code Online (Sandbox Code Playgroud)

并显式地将值放入其中:

  writeIORef xref (value_of_x_right_now + 15)
Run Code Online (Sandbox Code Playgroud)

显然,关于这些值,以及通常需要通过单子或另一个单子中的单子操作来访问它们的方式,还有很多可以说的IO

但是,即使抛开这一点,应该清楚的是,整数15和“内容被初始化为整数的容器15”是具有必然不同类型的对象。在这种情况下,类型分别是IntIORef Int

因此,数据结构的可变性必然会反映在类型级别,仅仅因为 Haskell 中的可变性是通过这些类型的“容器”实现的,并且值的类型与值的类型不同。包含该值的容器。