考虑到非安全性能,Haskell真的是一种纯粹的函数式语言吗?

考虑到非安全性能,Haskell真的是一种纯粹的函数式语言吗?,haskell,functional-programming,type-systems,referential-transparency,unsafe-perform-io,Haskell,Functional Programming,Type Systems,Referential Transparency,Unsafe Perform Io,Haskell通常被称为纯函数式语言的一个例子。鉴于存在System.IO.Unsafe.unsafePerformIO,如何证明这一点 编辑:我认为“纯功能性”意味着不可能将不纯净的代码引入程序的功能部分。语言/实现是纯功能性的。它包括两个“逃生舱口”,如果你不想使用,就不必使用。不幸的是,该语言必须进行一些真实的工作,这意味着与外部环境对话 好的方面是,您可以(而且应该)将这种“过时”代码的使用限制在程序中几个特定的、有良好文档记录的部分。我们称之为Haskell的语言 unsafePerf

Haskell通常被称为纯函数式语言的一个例子。鉴于存在
System.IO.Unsafe.unsafePerformIO
,如何证明这一点


编辑:我认为“纯功能性”意味着不可能将不纯净的代码引入程序的功能部分。

语言/实现是纯功能性的。它包括两个“逃生舱口”,如果你不想使用,就不必使用。

不幸的是,该语言必须进行一些真实的工作,这意味着与外部环境对话


好的方面是,您可以(而且应该)将这种“过时”代码的使用限制在程序中几个特定的、有良好文档记录的部分。

我们称之为Haskell的语言

unsafePerformIO
是外部功能接口规范的一部分,而不是核心规范。它可以用来产生局部的副作用,而这些副作用不会超出某些范围,以便公开一个纯粹的功能接口。也就是说,当类型检查器无法为我们执行时,我们使用它来隐藏效果(与ST monad不同,它使用静态保证隐藏效果)

为了精确地描述我们称之为“Haskell”的多种语言,请考虑下面的图像。每个环对应于一组特定的计算功能,按安全性排序,面积与表达能力相关(即,如果您具有该功能,您可以编写的程序数量)

< Haskell 98的语言被指定在中间,承认全部和部分函数。(或)在只允许全部函数的情况下,表达能力甚至更低,但“更纯粹”且更安全。而我们今天使用的Haskell包括了unsafePerformIO居住的FFI的所有信息。也就是说,你可以用现代的Haskell写任何东西,但是如果你使用外圈的东西,就很难通过内圈建立简单的安全保障

因此,Haskell程序通常不是由100%的引用透明代码构建的,但是,它是默认情况下唯一一种中等程度的纯公共语言

我认为“纯功能”意味着不可能引入不纯净的代码

真正的答案是
unsafePerformIO
不是Haskell的一部分,就像垃圾收集器或运行时系统是Haskell的一部分一样
unsafePerformIO
存在于系统中,因此构建系统的人员可以在非常有效的硬件上创建纯粹的功能抽象。所有真正的语言都有漏洞,这使得系统构建者能够以比使用C代码或汇编代码更有效的方式完成工作

至于副作用和I/O如何通过
IO
monad融入Haskell的更广泛的图景,我认为考虑Haskell最简单的方式是它是一种描述有效计算的纯语言。当所描述的计算是
main
时,运行时系统会忠实地执行这些效果


unsafePerformIO
是以不安全的方式获得效果的一种方式;“不安全”意味着“安全必须由程序员保证”-编译器不检查任何内容。如果您是一名精明的程序员,并且愿意履行严格的证明义务,那么可以使用
unsafePerformIO
。但在这一点上,您不再使用Haskell编程;您使用的是一种看起来很像Haskell的不安全语言进行编程。

我有一种感觉,说我将要说的话会非常不受欢迎,但我觉得我必须对这里提供的一些(我认为是错误的)信息做出回应

尽管unsafePerformIO确实作为FFI附录的一部分正式添加到语言中,但其原因主要是历史原因而非逻辑原因。它是非正式存在的,早在哈斯克尔拥有外国金融机构之前就被广泛使用。它从未正式成为哈斯克尔标准的一部分,因为正如你所观察到的那样,这太令人尴尬了。我想希望它会在将来的某个时候消失,不知怎么的。好吧,那还没有发生,在我看来也不会

FFI补遗的开发为unsafePerformIO进入官方语言标准提供了一个方便的借口,因为与添加调用外国(即C)代码的功能相比,这里的情况似乎并不太糟糕(在静态确保纯度和类型安全方面,所有赌注都被打掉了)。出于本质上的政治原因,把它放在这里也非常方便。它催生了这样一个神话:如果不是因为肮脏的“设计糟糕”的C、或“设计糟糕”的操作系统、或“设计糟糕”的硬件或..Haskell将是纯洁的。。无论什么毫无疑问,unsafePerformIO经常与FFI相关的代码一起使用,但其原因往往更多地与FFI以及Haskell本身的糟糕设计有关,而不是Haskell正在尝试的任何外来事物的糟糕设计

正如Norman Ramsey所说,官方的立场是,只要使用unsafePerformIO的人满足了某些证明义务,就可以使用unsafePerformIO(主要是这样做不会使重要的编译器转换无效,如内联和公共子表达式消除)。到目前为止一切都很好,或者人们可能会这么想。真正重要的是,这些证明义务无法通过unsafePerformIO最常见的一个用例来满足,据我估计,该用例占野外所有unsafePerformIO的50%以上。我说的是被称为“unsafePerformIO hack”的骇人听闻的习语,它(事实上显然)是完全不安全的