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