为可遍历结构实例化 Functor 和 Foldable
import Data.Traversable as Traversable
data MyType a = -- ...
instance Traversable MyType where
traverse = -- ...
每个 Traversable
结构都可以使用 Data.Traversable
中的 fmapDefault
和 foldMapDefault
函数制作一个 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)