Haskell:Haskell中的所有名称都是不可变的?数组和列表没有区别?

Haskell: all names in Haskell are immutable? No difference between array and list?

提问人:vik santata 提问时间:2/4/2016 最后编辑:Chris Martinvik santata 更新时间:2/4/2016 访问量:492

问:

我有两个问题:

  1. 在 scala 或 F# 等 FP 语言中,有一些关键字可以识别变量是否可变。当我们说 Haskell 是一种纯粹的 FP 语言时,一切都是“不可变的”?

  2. 基于 jvm 的 Scala、基于 .net 的 F# 都区分了 “Array” 和 “List”。Haskell是以不同的方式讲述的,还是Haskell中的每个容器都是一个“列表”或“元组”?

阵 列 列表 哈斯克尔 不变性 可变

评论

0赞 Chris Martin 2/4/2016
Haskell将突变形式化为IO(因为它就是这样)。例如,IORef 提供可变引用,Array.IO 提供可变数组。
2赞 dfeuer 2/4/2016
还有提供本地可变数组的状态线程 ()。ST

答:

1赞 Dietrich Epp 2/4/2016 #1

“纯洁”不是一个严格定义的概念。在Haskell中,这通常意味着函数没有副作用。但“副作用”也没有真正严格的定义。Haskell 的类型系统允许我们区分纯函数和非纯动作。并非所有内容都是不可变的,因为您可以使用 IO 操作来更改 的内容,例如。a -> bIO aIORef

Haskell也有数组,它们有几个不同的版本,但它们可以在你必须导入的模块中找到。

评论

3赞 dfeuer 2/4/2016
我想说的是,Haskell中的一切都是不可变的。 只是 Haskell 程序可以生成的一种类型,它被解释为命令式程序(在 Haskell 本身之外)。IO a
1赞 Dietrich Epp 2/4/2016
@dfeuer:你能详细说明一下这个论点吗?以一种无法执行或评估任何东西的方式定义“Haskell”有什么意义?
4赞 Ben 2/4/2016
部分原因在于,从某种意义上说,您可以在 Haskell 中使用 IO 进行纯计算,而不是执行它们。它们是一流的值,当你只是构建它们并传递它们时,所有关于纯 Haskell 代码的通常定律都适用(特别是当你将 monad 泛型函数应用于 IO 操作时)。只是执行方式不同,不难看出这是“外部的”,因为Haskell中没有语言设施可以真正谈论它(除了定义)。mainmain
1赞 dfeuer 2/4/2016
@DietrichEpp,康纳尔·埃利奥特(Conal Elliott)和其他人似乎认为,区分纯语言和任何交互概念都非常重要。FRP 旨在以与 .是的,这些天来,这最终是由一个有点短短的,但活动家认为这只不过是一个实现的产物。IOmain :: IO a
1赞 Dietrich Epp 2/4/2016
我知道能够区分它的不同部分很重要。但“纯洁”的部分之所以有用,是因为不纯洁的部分存在。说不纯洁的部分“不是哈斯克尔”是荒谬的。
3赞 MathematicalOrchid 2/4/2016 #2

在 Haskell 中,所有变量都是不可变。但是,有各种特殊的数据结构支持突变。首先,您可以在 Haskell 中读取和写入文件,并且可以将文件视为一个巨大的可变变量。当然,Haskell也支持内存中的可变结构(、、、等)。因此(例如)变量始终指向同一个对象,但该对象的内容可以更改。IORefSTRefMVarTVarxIORef

变异物质被认为是一种副作用,在Haskell中,这种副作用是通过单子控制的。如果函数的类型签名未提及 ,则无法执行任何 I/O 操作。这包括改变其他线程可以看到的内存中数据。(但是,有趣的是,它不包括仅对此函数可见的变异数据。因此,你可以在纯函数内部进行突变,只要没有外部可见的影响。IO

Haskell“默认”为不可变的单链表,但也支持不可变和可变数组。修改不可变数组需要复制整个数组,将更新转换为 O(n) 操作,从而破坏数组的一个关键优势。不可变数组仍然是常量数据的出色查找表,但大多数基于数组的算法都需要可变数组,这就是为什么也提供了这些数组的原因。