我有一个像这样定义的类,因此foo
采用泛型类型并返回一个Integer:
class Foo a where
foo :: a -> Integer
并定义了几个实例,因此它适用于Bool
和Char
类型:
instance Foo Bool where
foo _ = 10
instance Foo Char where
foo _ = 20
如果我现在想要为具有泛型类型的列表添加实例,我希望这样做:
instance Foo [a] where
foo (t:ts) = (foo t) + (foo ts)
然而,这是错误的。根据我目前的理解,我想假设Haskell推断类型并执行类似的操作:
foo [False,True] - > foo False + foo True - > 10 + 10 = 20
我看过几本书并阅读了关于多态性和类型类的内容,包括了解大好的Haskell!但仍然无法解决如何解决这个问题?
答案 0 :(得分:6)
您需要说列表必须包含Foo
值:
instance Foo a => Foo [a] where
foo (h:t) = foo h + foo t
foo [] = 0
当foo h
是h
实例时,您只能调用Foo
,因此您需要限定[a]
的类型类,以便它仅适用于{的列表{1}}个实例。
否则,例如,如果您有Foo
,则[Int]
意味着您尝试在foo h
值上调用foo
,但Int
未针对该类型定义。
通过foo
的上述实现,您可以得到预期的结果:
[a]
答案 1 :(得分:3)
你忘了基本情况:
instance Foo a => Foo [a] where
foo (t:ts) = foo t + foo ts
foo [] = 0
请注意,调用foo ts
不意味着我们在第二个元素上调用foo
。我们实际上以递归方式调用我们定义的函数(粗体为foo
),因此这将继续在列表的元素上调用foo
,直到列表用完为止,在这种情况下,将使用基本案例foo [] = 0
。
所以它会评估:
foo (False : True : [])
-> foo False + foo (True : [])
-> 20 + foo (True : [])
-> 20 + foo True + foo []
-> 20 + 20 + foo []
-> 20 + 20 + 0
-> 20 + 20
-> 40
->