为可遍历结构实例化 Functor 和 Foldable

import Data.Traversable as Traversable

data MyType a =  -- ...
instance Traversable MyType where
    traverse = -- ...

每个 Traversable 结构都可以使用 Data.Traversable 中的 fmapDefaultfoldMapDefault 函数制作一个 Traversable Functor

instance Functor MyType where
    fmap = Traversable.fmapDefault

instance Foldable MyType where
    foldMap = Traversable.foldMapDefault

fmapDefault 是通过在 Identity applicative functor 中运行 traverse 来定义的。

newtype Identity a = Identity { runIdentity::a }

instance Applicative Identity where
    pure = Identity
    Identity f <*> Identity x = Identity (f x)

fmapDefault::Traversable t => (a -> b) -> t a -> t b
fmapDefault f = runIdentity . traverse (Identity . f)

foldMapDefault 是使用 Const applicative functor 定义的,它忽略了它的参数,同时累积了一个 monoidal 值。

newtype Const c a = Const { getConst::c }

instance Monoid m => Applicative (Const m) where
    pure _ = Const mempty
    Const x <*> Const y = Const (x `mappend` y)

foldMapDefault :: (Traversable t, Monoid m) => (a -> m) -> t a -> m
foldMapDefault f = getConst . traverse (Const . f)