18

たとえば、Data.Mapのインターンについてもっとよく理解したいと思います。マップに新しいバインディングを挿入すると、データが不変であるため、古いデータ構造に新しいバインディングを加えたものと同じ新しいデータ構造が返されます。

これがどのように達成されるのかを理解したいと思います。コンパイラは最終的に、たとえば数百万のバインディングを使用してデータ構造全体をコピーすることにより、これを実装しますか?このような場合、可変データ構造/配列(Data.Judyなど)または命令型プログラミング言語のパフォーマンスが向上すると一般的に言えますか?辞書/Key-Valueストアに関して、不変データには利点がありますか?

4

3 に答える 3

32

Mapツリーデータ構造に基づいて構築されています。基本的に、新しいMapが作成されますが、古い構造へのポインターでほぼ完全に埋められます。Haskellでは値が変わることはないので、これは安全で非常に重要な最適化であり、共有として知られています。

これは、同じデータ構造の多くの類似したバージョンをぶら下げることができることを意味しますが、異なるツリーのブランチのみが新しく保存されます。残りは、ブランチの元のコピーへのポインタになります。そしてもちろん、古いものを捨てると、変更Mapしたブランチガベージコレクターによって回収されます。

共有は、不変のデータ構造のパフォーマンスの鍵です。このウィキペディアの記事が役立つかもしれません。変更されたデータが共有によってどのように表されるかを示すいくつかの啓発的なグラフがあります。

于 2012-04-03T23:41:28.367 に答える
15

いいえ。のドキュメントにData.Map.insertは、挿入にはO(log n)時間がかかると記載されています。構造全体をコピーしなければならない場合、その限界を満たすことは不可能です。

于 2012-04-03T23:48:50.250 に答える
5

Data.Map は古いマップをコピーしません。それは (怠惰に) O(log N) 個の新しいノードを割り当てます。これらのノードは古いマップのほとんどを指します (したがって共有します)。

マップを「更新」しても古いバージョンが中断されないため、この種のデータ構造により、並行アルゴリズムを構築する際の自由度が高まります。

于 2012-04-04T00:16:30.627 に答える