2015-04-06 54 views
0

我試圖爲Huffman樹數據結構實現EqOrd,但我得到了幾個「模糊定義」和範圍相關的錯誤。我一直在下面的https://www.haskell.org/tutorial/classes.html嘗試爲自定義樹數據結構定義Eq時出現模糊的定義錯誤

import Data.List 

data Tree a = Leaf a Int | Internal (Tree a) (Tree a) Int deriving (Eq, Ord) 

instance (Eq a) => Eq (Tree a) where 
(Leaf a ac) == (Leaf b bc) = (a == b) && (ac == bc) 
(Internal (Tree a1) (Tree a2) ac) == (Internal (Tree b1) (Tree b2) bc) = 
        (a1 == b1) && (a2 == b2) && (ac == bc) 
_ == _ = False 

instance Ord (Tree a) where 
Tree a <= Tree b = (freq a) <= (freq b) 

freq :: Tree a -> Int 
freq (Leaf _ c) = c 
freq (Internal _ _ c) = c 

樹例子,我不知道什麼是不明確的。它表示==可能來自Prelude或我的代碼。但是,我的==只是爲我的Tree定義的,所以我不確定發生了什麼。請幫我理解並糾正這個問題。

+0

您正在爲'Tree'派生'Eq'和'Ord'。那你爲什麼要寫它的實例? – Sibi

+0

除了bheklir所說的你使用Tree進行模式匹配之外,Tree是一個類型構造函數而不是Data構造函數。你只能使用數據構造函數模式匹配葉或內部 – felipez

+0

@Sibi我可能會誤解某些東西,但我的理解是Eq和Ord是接口,並且我提供了Eq和Ord的具體實現。我來自Java背景。 – ssh

回答

4

問題是縮進。您需要使用==<=縮進所有行。編譯器將instance (Eq a) => Eq (Tree a) where看作一個塊,然後樹上的==定義爲完全獨立的代碼塊。縮進這個和你的Tree a <= Tree b = ...行,它應該是很好的去。否則,它看起來像是在源代碼的頂層定義==,Haskell很高興讓你這樣做。

由於您已經爲Tree推導出EqOrd,因此您不必親自定義它們。如果你想在這裏定製實例,那麼不要派生它們。除此之外,你需要修復的定義爲您的Ord實例只是

instance Ord (Tree a) where 
    a <= b = freq a <= freq b 

freq相同的定義。你不需要在這裏進行模式匹配,特別是因爲Tree是一個類型構造函數,但是你只能對數據構造函數進行模式匹配。 LeafInternal這裏是數據構造函數,所以它們可以在模式上匹配。你也需要爲你的Eq實例解決這個問題,但解決方案是類似的。

+0

非常感謝您的幫助! – ssh