[英]Haskell generic typeclass with list
I have a class defined like this, so that foo
takes a generic type and returns an Integer: 我有一个像这样定义的类,所以
foo
采用泛型类型并返回一个Integer:
class Foo a where
foo :: a -> Integer
and a couple of instances defined so it will work with Bool
and Char
types: 并定义了几个实例,以便它可以与
Bool
和Char
类型一起使用:
instance Foo Bool where
foo _ = 10
instance Foo Char where
foo _ = 20
If I now want to add an instance for a list with a generic type, I would want to do something like this: 如果我现在想要为具有泛型类型的列表添加实例,我想要做这样的事情:
instance Foo [a] where
foo (t:ts) = (foo t) + (foo ts)
However, this is wrong. 但是,这是错误的。 From my current understanding, I would want to assume that Haskell infers the types and does something like this:
根据我目前的理解,我想假设Haskell推断出类型,并做了类似这样的事情:
foo [False,True] -> foo False + foo True -> 10 + 10 = 20
foo [False,True] - > foo False + foo True - > 10 + 10 = 20
I've looked at several books and read about polymorphism and typeclasses, including Learn You a Haskell For Great Good! 我看过几本书并阅读了关于多态性和类型类的知识,包括了解大好的Haskell! but still can't wrap my head around how to solve this?
但仍然无法绕过如何解决这个问题?
You need to say that the list must contain Foo
values: 你需要说列表必须包含
Foo
值:
instance Foo a => Foo [a] where
foo (h:t) = foo h + foo t
foo [] = 0
You can only call foo h
when h
is a Foo
instance, so you need to qualify the type class for [a]
so that it only works for lists of Foo
instances. 当
h
是Foo
实例时,您只能调用foo h
,因此您需要为[a]
限定类型类,以便它仅适用于Foo
实例的列表。
Otherwise, if, for instance, you had a [Int]
, foo h
would imply that you'd try to call foo
on an Int
value, but foo
isn't defined for that type. 否则,例如,如果你有
[Int]
, foo h
意味着你试图在Int
值上调用foo
,但是没有为该类型定义foo
。
With the above implementation for [a]
you get expected results: 通过
[a]
的上述实现,您可以得到预期的结果:
Prelude> foo [True,False,True]
30
Prelude> foo [True,False,True,True]
40
Prelude> foo "foo"
60
You forgot the base case: 你忘了基本情况:
instance Foo a => Foo [a] where
foo (t:ts) = foo t +
foo ts
foo [] = 0
Mind that the call foo ts
does not mean that we call foo
on the second element. 记住,调用
foo ts
并不意味着我们称之为foo
的第二个元素上。 We actually call recursively the function we define (the foo
in boldface), and this will thus keep calling foo
on the elements of the list, until the list is exhausted, in which case the base case foo [] = 0
will be used. 我们实际上递归地调用我们定义的函数(粗体表示
foo
),因此这将继续在列表的元素上调用foo
,直到列表用完为止,在这种情况下将使用基本情况foo [] = 0
。
So it will evaluate: 所以它将评估:
foo (False : True : [])
-> foo False + foo (True : [])
-> 20 + foo (True : [])
-> 20 + foo True + foo []
-> 20 + 20 + foo []
-> 20 + 20 + 0
-> 20 + 20
-> 40
->
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.