私はハスケル(数ヶ月)を使い慣れました。私は大きな表現DAG(樹木、DAGではない)、深く潜在的に複数の合流する経路(すなわち、根から葉までの異なる経路の数が巨大である)をアセンブルするHaskellプログラムを持っています。私は、等価のためにこれらのダグをテストするための速い方法が必要です。デフォルトのEqの導出は、同じノードを複数回探検するだけです。現在のところ、私のプログラムは比較的小さな表現では60秒かかり、大きなものでは終了しません。プロファイラは、ほとんどの時間平等をチェックしていることを示しています。私はこの問題がないカスタムEqを実装したいと思います。私はこの問題を解決する方法がありませんが、多くの書き換えを必要としません。だから私はあなたの考えを聞きたい。ハスケルの大規模なDAG構造の等価性テスト
私が最初に試みたのは、ツリーを構築するときに、Data.Hashable.hash
を使用して、徐々に計算するハッシュを持つツリーノードを計測することでした。このアプローチは、構造を深く見ない限り、2つのものが等しいかどうかをテストする簡単な方法を与えました。しかし、多くの場合、このDAGでは、DAGマージのパスのために、構造は実際には等しいです。だからハッシュは平等で、私は完全な吹き飛ばされた平等テストに戻ります。
もし私が物理的平等を行う方法を持っていたら、ここでの私の多くの問題は消え去ります。物理的に同等であれば、それはそれです。それ以外の場合、ハッシュが異なる場合はそれがそれです。物理的には同じではないが、ハッシュに同意する場合にのみより深く進んでください。
また、gitを模倣し、ノードごとにSHA1を計算して、それらが等しい期間(再帰を必要としない)であるかどうかを判断することもできます。私は、これが助けになるという事実を知っています。ハッシュ平等の観点から平等を完全に決めると、プログラムは最大の表現に対して数十ミリ秒で実行されるからです。このアプローチには、何らかの理由で同じ2つの等しいダグが物理的に等しいのではなく内容が等しい場合、その場合でも高速に検出できるという利点があります。 (Idでは、Idはその時点でまだトラバーサルを行う必要があります)。だから私はセマンティクスがもっと好きです。
しかし、この手法では、Data.Hashable.hash
関数を呼び出すよりもはるかに多くの作業が必要になります。これは、ダグノードタイプのすべての変種に対して派生させる必要があるためです。さらに、ノード定義が多少異なる複数のダグ表現があるため、表現を追加する場合は、基本的にこのハッシュトリックを2回以上行う必要があります。
あなたは何をしますか?
カスタム関数で '(==)'を定義する方法や、あなたのニーズに最も適したカスタム関数は何ですか? btw、私はあなたが他の言語からそれを知っているように "物理的平等"はhaskellに存在するとは思わない、あなたは単純にあなたの 'class Eq a where(==)を定義するだけで、 ....それはそれです... – mb21
@ mb21彼は 'Eq'の効率的なインスタンスを定義する方法や、' Eq'のデフォルトインスタンスが効率的なDAGのデータ構造を定義する方法を尋ねています。 .. 2つのうちどちらがどちらであるかわからないし、コードを与えてもほとんど役に立たない。 – Bakuriu