我是Haskell的新手(幾個月)。我有一個Haskell程序,它組裝一個大型表達式DAG(不是一棵樹,一個DAG),可能很深並具有多個合併路徑(即從根到葉的不同路徑的數量很大)。我需要一種快速的方法來測試這些dags的平等性。默認的Eq派生只會遞歸,多次探索相同的節點。目前,這會導致我的程序花費60秒來處理相對較小的表達式,甚至無法完成較大的表達式。分析器指示大部分時間都忙於檢查相等性。我想實現一個沒有這個問題的自定義Eq。我沒有辦法解決這個不涉及大量重寫的問題。所以我想聽聽你的想法。Haskell中大DAG結構的Eq測試
我的第一次嘗試是用我在構建樹時使用Data.Hashable.hash
遞增計算的散列來「測量」樹節點。這種方法給我一個簡單的方法來測試兩件事情是不平等的,沒有深入研究結構。但通常在這個DAG中,由於DAG合併中的路徑,結構確實是相等的。所以哈希值是平等的,我恢復到全面的平等測試。
如果我有辦法做物理平等,那麼我在這裏的很多問題就會消失:如果他們在物理上是平等的,那就是了。否則,如果哈希是不同的,就是這樣。如果它們在物理上不一樣,只能更深入,但它們的散列同意。
我也可以模仿git,並計算每個節點的SHA1以決定它們是否等於週期(不需要遞歸)。我知道這樣做會有所幫助,因爲如果我通過散列相等來完全決定相等性,那麼程序將在幾十毫秒內運行最大的表達式。這種方法也有很好的優點,如果由於某種原因有兩個相同的dag不是物理上相同的,但是內容相同,那麼我也能夠在這種情況下快速檢測到它。 (對於Id,Id仍然必須在該點進行遍歷)。所以我更喜歡語義。
然而,這種方法涉及比調用Data.Hashable.hash
函數更多的工作,因爲我必須爲每個dag節點類型的變體推導它。此外,我有多個DAG表示,具有稍微不同的節點定義,所以如果我決定添加更多的表示形式,我需要基本上做兩次或更多的哈希技巧。
你會怎麼做?
你在問怎麼用自定義函數定義'(==)',或者什麼自定義函數最適合你的需求?這個問題有點臃腫/混亂,因爲它現在... btw,我不認爲「物理平等」,因爲你知道它存在於haskell中的其他語言,你只需定義你的'class Eq a where(==) ....'就是這樣...... – mb21
@ mb21他要麼是要求如何爲'Eq'定義一個有效的實例,要麼是如何爲他的DAG定義一個數據結構,而'Eq'的默認實例是有效的。 ..不知道這兩個中的哪一個,並且沒有給出我們可以提供一點幫助的代碼。 – Bakuriu