為可遍歷結構例項化 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)