Data structures 纯功能数据结构的好处是什么?

Data structures 纯功能数据结构的好处是什么?,data-structures,haskell,functional-programming,ocaml,purely-functional,Data Structures,Haskell,Functional Programming,Ocaml,Purely Functional,有大量关于数据结构的文本和数据结构代码库。我知道纯功能数据结构更容易推理。然而,我很难理解在实用代码中使用纯函数数据结构(使用函数式编程语言或不使用函数式编程语言)相对于命令式代码的实际优势。有人能提供一些纯功能数据结构具有优势的真实案例吗?为什么 类似于我使用编程语言中的数据结构名称来执行应用程序,因为它可以执行某些事情 谢谢 PS:我所说的纯功能数据结构与持久数据结构不同。持久数据结构是一种不变的数据结构??另一方面,纯功能数据结构是一种纯操作的数据结构。Erlang程序几乎完全使用纯功能数

有大量关于数据结构的文本和数据结构代码库。我知道纯功能数据结构更容易推理。然而,我很难理解在实用代码中使用纯函数数据结构(使用函数式编程语言或不使用函数式编程语言)相对于命令式代码的实际优势。有人能提供一些纯功能数据结构具有优势的真实案例吗?为什么

类似于我使用编程语言中的数据结构名称来执行应用程序,因为它可以执行某些事情

谢谢


PS:我所说的纯功能数据结构与持久数据结构不同。持久数据结构是一种不变的数据结构??另一方面,纯功能数据结构是一种纯操作的数据结构。

Erlang程序几乎完全使用纯功能数据结构,通过几乎无缝地扩展到多个核心,它们获得了巨大的好处。因为共享数据(主要是二进制文件和位字符串)从未被修改过,所以永远不需要锁定这些数据。

以F#的这一小片段为例:

你可以100%肯定地说,这是一个由1到5的整数组成的不可变列表。您可以传递对该列表的引用,而不必担心该列表可能已被修改。这就是我使用它的充分理由

纯功能(也称为持久或不可变)数据结构为您提供了几个优势:

  • 您不必锁定它们,这极大地提高了并发性
  • 它们可以共享结构,从而减少内存使用。例如,考虑Haskell中的列表[1, 2, 3,4 ]和java之类的命令性语言。要在Haskell中生成新列表,您只需创建新的
    cons
    (一对值和对下一个元素的引用)并将其连接到上一个列表。在Java中,您必须创建一个全新的列表,以免损坏上一个列表
  • 您可以创建持久数据结构
  • 此外,如果您使用函数式,您可以避免考虑操作的时间和顺序,从而使您的程序更加灵活
  • 事实上,数据结构是不可变的,允许您进行更多的假设,从而扩展语言的功能。例如,使用不变性的事实在每个对象上正确提供hashCode()方法的实现,因此任何对象都可以用作映射中的键
  • 使用不变的数据和功能样式,您还可以自由使用

总的来说,它有更多的优点,它是模拟真实世界的另一种方式。SICP中的其他章节将为您提供更准确的视图,说明使用不变结构编程的优点和缺点

除了共享内存安全之外,大多数纯功能数据结构还提供持久性,而且实际上是免费的。例如,假设我在OCaml中有一个
集合
,我想向它添加一些新值,我可以这样做:

module CharSet = Set.Make(Char)
let a = List.fold_right CharSet.add ['a';'b';'c';'d'] CharSet.empty in
let b = List.fold_right CharSet.add ['e';'f';'g';'h'] a in
...
a
在添加新字符后保持未修改(它只包含a-d),而
b
包含a-h,它们共享一些相同的内存(使用
set
很难判断共享了多少内存,因为这是一个AVL树,树的形状会发生变化)。我可以继续这样做,跟踪我对树所做的所有更改,使我能够返回到以前的状态

下面是来自的一个很好的图表,显示了将字符“e”插入二叉树的结果
xs


纯功能数据结构具有以下优点:

  • 持久性:旧版本可以安全地重用,因为它们不能被更改

  • 共享:一个数据结构的多个版本可以同时保存,只需要少量的内存需求

  • 线程安全:任何变异都隐藏在lazy thunk(如果有)中,因此由语言实现处理

  • 简单性:不必跟踪状态更改,使纯功能数据结构更易于使用,特别是在并发上下文中

  • 增量:纯功能数据结构由许多小部分组成,非常适合增量垃圾收集,从而降低延迟

请注意,我没有将并行性列为纯函数数据结构的优势,因为我不相信这种情况。高效的多核并行性需要可预测的局部性,以便利用缓存并避免在共享访问主内存时遇到瓶颈,而纯功能数据结构在这方面最多具有未知的特性。因此,许多使用纯功能性数据结构的程序在多核上并行化时无法很好地扩展,因为它们将所有时间都花在缓存未命中上,争夺共享内存路径

我所说的纯功能性数据结构与持久性数据结构不同


这里有些混乱。在纯功能数据结构的上下文中,持久性是一个术语,用于指在数据结构仍然有效的情况下安全地引用以前版本的能力。这是纯功能的自然结果,因此,持久性是所有纯功能数据结构的固有特征。

请注意,由F#实现的单链表是纯功能数据结构:您所说的“纯”是什么意思,它不同于不可变?不可变性是
module CharSet = Set.Make(Char)
let a = List.fold_right CharSet.add ['a';'b';'c';'d'] CharSet.empty in
let b = List.fold_right CharSet.add ['e';'f';'g';'h'] a in
...