首页 文章

Haskell通用类型类与列表

提问于
浏览
3

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

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

我看过几本书并阅读了关于多态性和类型类的知识,包括了解大好的Haskell!但仍然无法绕过如何解决这个问题?

2 回答

  • 6

    您需要说列表必须包含 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
    
  • 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
    ->
    

相关问题