【问题标题】:Haskell generic typeclass with list带有列表的 Haskell 泛型类型类
【发布时间】:2018-01-25 11:43:55
【问题描述】:

我有一个这样定义的类,所以foo 采用泛型类型并返回一个整数:

class Foo a where
  foo :: a -> Integer

并定义了几个实例,使其适用于 BoolChar 类型:

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

我看过几本关于多态性和类型类的书籍,包括 Learn You a Haskell For Great Good!但还是不知道如何解决这个问题?

【问题讨论】:

  • 为什么会出错?你忘记了基本情况。
  • 我确实做到了。在我试图解决主要问题时忽略了它。
  • 下一步是data AnyFoo = forall a. Foo a => AnyFoo a 和它的实例:)

标签: haskell generics typeclass


【解决方案1】:

你需要说列表必须包含Foo值:

instance Foo a => Foo [a] where
  foo (h:t) = foo h + foo t
  foo [] = 0

hFoo 实例时,您只能调用foo h,因此您需要限定[a] 的类型类,以便它仅适用于Foo 实例的列表。

否则,例如,如果您有一个 [Int]foo h 将意味着您尝试在 Int 值上调用 foo,但 foo 没有为该类型定义.

通过[a] 的上述实现,您将获得预期的结果:

Prelude> foo [True,False,True]
30
Prelude> foo [True,False,True,True]
40
Prelude> foo "foo"
60

【讨论】:

  • 所以在某种程度上,添加类约束会告诉它与 Foo 类中的类型匹配,就像将类约束更改为 Eq 会告诉它在 Eq 类型类中查找匹配一样?
  • @tem887 我不确定您所说的 寻找匹配项 是什么意思,但如果该短语适合您... :) 我的想法是不是 a 类型完全不受约束,而是类约束 Foo a 声明只允许那些也是 Foo 实例的 a 类型。
  • 更简单的定义是foo = sum . map foo
【解决方案2】:

您忘记了基本情况:

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
->

【讨论】:

  • 是的,我知道。 ts 在这种情况下是列表的尾部,即剩余的元素。我只是想用几个步骤举一个简单的例子:-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-15
  • 1970-01-01
相关资源
最近更新 更多