类型类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
的内容,其中a
和b
类型
是不同的。
以下代码显示了一个不编译的示例:
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
定义可折叠的实例,其中a
和b
类型真的不同?
答案 0 :(得分:5)
问题不在于类型不同。您foldr
的类型与Foldable
所需的类型不同。它需要是:
foldr :: (a -> b -> b) -> b -> Tree a -> b
这些a
和b
类型参数必须保留为参数:对于a
和b
的所有选项,必须使用。您不能将它们约束到其他类型类,并且您不能将其中一个限制为具体的Int
类型。
答案 1 :(得分:1)
似乎您可以通过使用实际的foldr
函数而不是修改它来实现您想要的。您无法更改类型类方法的签名,在这种情况下,不需要。尝试通过提供其类型的合理实现来实现foldr
,然后编写一个函数addSize
,可以作为第一个参数传递给foldr
。 foldr addSize 0
将拥有您想要的行为。