2013-10-14 6 views
11

Schemeでは、プリミティブeq?は、その引数が同じオブジェクトであるかどうかをテストします。例えば、以下のリストハスケルでの共有を検出することは可能ですか?

(define lst 
    (let (x (list 'a 'b)) 
    (cons x x))) 

(eq? (car x) (cdr x)) 

の結果は真であり、しかもそれはが(car x)(cdr x)にピアすることなく、真です。これにより、多くの共有を持つデータ構造に対して効率的な等価性テストを書くことができます。

ハスケルでも同じことが可能ですか?たとえば、次のバイナリツリーの実装を考えてみましょう。すべてのレベルで共有されているバイナリツリーの実装を考えてみましょう。 let tree = mkTree 30のツリーを作成して、left treeright treeが等しいかどうかを知りたい場合は、10億ノードを越えてデータを共有する必要があります。

ハスケルでのデータ共有を簡単に発見する方法はないと思いますが、このような問題に対処する典型的な方法は、効率的な目的で共有を検出するのが得策でしょうか?周期的なデータ構造を検出する)。

unsafe共有を検出できるプリミティブがありますか?明示的なポインタを持つデータ構造を構築するためのよく知られた方法があるので、ポインタの等価性を比較できますか?

+0

も参照してください。http://stackoverflow.com/questions/1717553/pointer-equality-in-haskell – Yuras

+0

これを実行するときには、データ構造にNaNなどの値が含まれていない可能性が常に考えられます。自分自身。あなたの最適化は壊れやすいかもしれません。 – rightfold

答えて

16

多くのアプローチがあります。

  1. 一意のIDを生成し、すべてを有限マップ(例:IntMap)に貼り付けます。
  2. 最終的な選択の洗練されたバージョンは、明示的なグラフを作成することです。 fglを使用してください。
  3. stable namesを使用してください。
  4. IORefssee also)です。これは、含まれるタイプに関係なく、EqOrdの両方のインスタンスを持ちます。
  5. observable sharingのライブラリがあります。
  6. 上記のとおり、reallyUnsafePtrEquality#がありますが、使用する前に実際には何が安全でないのかを理解する必要があります。

this answer about avoiding equality checks altogetherも参照してください。

4

純粋な言語ハスケルでは不可能です。

しかし、GHCでの実装では、このような

いずれにしても、これを通常のコードで使用すると非常にユニートリマティックです。せいぜい、私は、何か(メモ帳、ハッシュテーブルなど)のための高度に専門化されたライブラリを構築して、純粋で純粋なAPIを提供することが受け入れられるかもしれないと想像することができます。

関連する問題