是否可以使用foldr定义Data.Foldable的实例,其中foldr接受不同类型的参数?

时间:2017-09-19 10:52:50

标签: haskell typeclass

类型类Data.Foldable具有以下定义:

class Foldable t where
    {-# MINIMAL foldMap | foldr #-}
    foldMap :: Monoid m => (a -> m) -> t a -> m
    foldr :: (a -> b -> b) -> b -> t a -> b
    ....
    <more definitions>

最小节说,我只能使用 foldr 函数定义一个实例。 在我可以编译的所有示例中,foldr函数具有类型a -> a -> a。但是,我无法做到 定义 foldr 函数真正键入a -> b -> b的内容,其中ab类型 是不同的。

以下代码显示了一个不编译的示例:

import Data.Foldable

data Tree a = Tree a a | Leaf a

class Size a where
   size :: a -> Int 

instance Size a => Foldable (Tree a) where
  foldr :: a -> Int -> Int
  foldr x n = size x + n

是否可以使用foldr定义可折叠的实例,其中ab类型真的不同?

2 个答案:

答案 0 :(得分:5)

问题不在于类型不同。您foldr的类型与Foldable所需的类型不同。它需要是:

foldr :: (a -> b -> b) -> b -> Tree a -> b

这些ab类型参数必须保留为参数:对于ab的所有选项,必须使用。您不能将它们约束到其他类型类,并且您不能将其中一个限制为具体的Int类型。

答案 1 :(得分:1)

似乎您可以通过使用实际的foldr函数而不是修改它来实现您想要的。您无法更改类型类方法的签名,在这种情况下,不需要。尝试通过提供其类型的合理实现来实现foldr,然后编写一个函数addSize,可以作为第一个参数传递给foldrfoldr addSize 0将拥有您想要的行为。