Haskell 的纯度是由类型系统还是 IO 的实现强制执行的?

Is Haskell's purity enforced by the type system or IO's implementation?

人们总是说 Haskell 的类型系统可以防止不纯代码污染纯代码,因为您总是必须在类型签名中指定 IO。但是,这是类型系统本身的结果,还是真的只是 IO(..) 没有导出?

基本上,如果类型构造函数可用,是否可以完成类似的事情?

ioToPure :: IO a -> a
ioToPure (IO ioValue) = ioValue

是的,这在某种意义上是正确的。

类型系统本身对 IO 一无所知,也不需要。不同的语言特性向用户隐藏了 IO 操作的真实表示,因此不可能 "just run" IO 操作。

所以,事实是,Haskell 和类似语言的 IO 安全性是多种语言特性和属性的综合结果,最突出的是:

  • 不接受用户 "shut up, I know better" 的强类型系统。
  • 一切都是打出来的属性。我在这里的意思是,在不纯的语言中,你有 "statements" 并且即使类型系统很强大,它也不会超过下一个分号。而在 Haskell 中,我们只有表达式,每个表达式的每一位都有一个类型,并最终影响表达式所在函数的类型。
  • 隐藏类型表示的语言特性。

尽管如此,我认为表达式 "the type system makes sure that impure and pure code is separated" 是一种无害的简化。

当然,导出低级基元可能会在任何地方产生副作用。 而且,是的,你可以通过避免出口每一种危险的东西来获得纯度。不需要类型级机器。

但是,如果没有类型限制,所有与 IO 相关的内容都会很危险。所以我们会完全禁止 IO。没什么用。

在类型系统的帮助下,相反,我们可以导出一些 "dangerous" IO 操作,知道它们只能在 "controlled" 个地方执行,这些地方必须带有 IO 标签在他们的类型中。让他们不再危险。

因此,纯度来自静态保证和谨慎导出的结合。