2011-05-25 115 views
4

我一直在試圖寫一個小文件來嘗試一個袋狀數據結構。到目前爲止,我的代碼如下:Haskell數據結構奇怪

data Fruit = Apple | Banana | Pear deriving (Eq, Show) 
data Bag a = EmptyBag | Contents [(a, Integer)] 

emptyBag :: Bag a 
emptyBag = EmptyBag 

unwrap :: [a] -> a 
unwrap [x] = x 

isObject theObject (obj, inte) = theObject == obj 

count :: Bag a -> a -> Integer 
count (Contents [xs]) theObject = snd (unwrap (filter (isObject theObject) [xs])) 
count EmptyBag _ = 0 

但是當我嘗試運行它,我得到的錯誤 無法推斷(公式一)從在使用「則IsObject」所產生的上下文() 。 ...

,當我把COUNT函數並調用 SND而(解包(過濾器(香蕉則IsObject)(蘋果,1),(香蕉,2))) 它興高采烈地返回2

任何線索爲什麼這是,或建議寫這種數據結構將不勝感激。

+1

不需要'EmptyBag'構造函數;改用'Contents []'。 – augustss 2011-05-25 19:51:19

+0

當你嘗試像'count(Contents [(Banana,2),(Apple,3)])Apple'那樣''[xs]''只與一個元素的列表匹配時'count'也會崩潰! – yatima2975 2011-05-25 20:22:25

回答

6

(==)只能在包含Eq的上下文中使用,但是當您聲明count時,您沒有包含該上下文。如果我讀正確,這將是

count :: Eq a => Bag a -> a -> Integer 

如果聲明count不包括類型,你可以問ghci爲推斷出的類型;或者只是要求推斷的類型snd (unwrap (filter (isObject Banana) [(Apple,1),(Banana,2)]))

+0

你的解決方案是正確的,但我不完全明白爲什麼;我推測,因爲函數isObject用於比較,它不會停止在這種情況下工作 - 在程序中添加Eq a =>的確切原因是什麼? – Owen 2011-05-25 15:50:26

+0

'Eq a'告訴你的編譯器'theObject'是'Eq'類型類的成員 - 也就是說,你可以測試它是否與其他類型相同。有一些數據類型(函數是最好的例子),它們不是'Eq'類型類的成員。 (例如,(+1)和((+2)。( - 1))不能測試相等性,儘管在幾乎所有情況下它們都會返回相同的結果。) – dvitek 2011-05-25 15:52:34

+0

暗中,類型類函數=)'在包含關於類型的信息的表中查找; 'Eq a =>'聲明瞭該表的類型,該表的類型在幕後作爲附加參數傳遞。 (如果你看GHC核心輸出,你會看到實際的表被傳遞。)用'isObject'你讓GHC自己處理這個類型,並且這樣做,包括'Eq a'約束;但是當你自己指定'count'的類型時,你不會留下這樣的東西(至少不是一些相當多毛的Oleg-isms)。這是全部或沒有。 – geekosaur 2011-05-25 15:55:23