2011-05-25 91 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