具有“可折叠”类型约束的折叠类型签名

Fold type signature with `Foldable` type constraint

在我的 GHCi foldrfoldl 上有这个签名:

Prelude> :t foldr
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
Prelude> :t foldl
foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b

折叠的替代类型签名有什么区别,特别是 t a 部分?

fr :: (a -> b -> b) -> b -> [a] -> b
fl :: (b -> a -> b) -> b -> [a] -> b

类型 class Foldable 除了 foldl.

之外还定义了一些函数
class Foldable t where
    foldMap :: Monoid m => t m -> m
    foldr :: (a -> b -> b) -> b -> t a -> b
    foldl :: (b -> a -> b) -> b -> t a -> b
    -- ...

我们可以通过至少定义 foldMapfoldr 来为类型构造函数 t 定义 Foldable 实例 对于类型。 (foldl 有一些其他的默认定义,因此只要您提供最小定义,您就可以为 "free" 获得它。

instance Foldable [] where
    foldr f b [] = b
    foldr f b (x:xs) = f x : foldr f b xs

instance Foldable Maybe where
    foldr f b Nothing = b
    foldr f b (Just a) = f b a

类型签名中的 t 只是意味着只要类型构造函数为其定义了一个 Foldable 实例,您就可以使用具有适当值的 foldl类型。例如:

Prelude> foldl (+) 0 [1,2,3]
6
Prelude> foldl (+) 0 []
0
Prelude> foldl (+) 0 Nothing
0
Prelude> foldl (+) 0 (Just 3)
3

前两种情况,我们使用[]实例,因为t a对应的参数是列表,也就是说t统一[],写作 t ~ []。在后两个中,我们使用 Maybe 实例,因为 t a 对应的参数是 Maybe 值,所以 t ~ Maybe.