简体   繁体   English

Haskell通用类型类与列表

[英]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: 并定义了几个实例,以便它可以与BoolChar类型一起使用:

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. hFoo实例时,您只能调用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM