你的两个例子都是函子的箭头映射(不是Functors,而是更广泛分类意义上的函子),就像fmapa 的箭头映射一样Functor。(=<<),例如,是某个 monad的函子从Kleisli m到的箭头映射。因此,适当的概括是解释不同类别之间的函子的概括。规定:(->)mControl.Categorical.Functor
class (Category r, Category t) => Functor f r t | f r -> t, f t -> r where
fmap :: r a b -> t (f a) (f b)
有了它,您将能够本着以下精神编写一个实例:
-- `(.)` is plain old Prelude `(.)`, and not the generalised `Category` one.
instance Monad m => Functor m (Kleisli m) (->) where
fmap = (=<<) . runKleisli
或者,对于您可以实际运行的东西:
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import Control.Arrow (Kleisli(..))
import qualified Control.Categorical.Functor as F
newtype BindF m a = BindF { runBindF :: m a }
deriving (Functor, Applicative, Monad, Show)
instance Monad m => F.Functor (BindF m) (Kleisli (BindF m)) (->) where
fmap = (=<<) . runKleisli
GHCi> F.fmap (Kleisli (BindF . replicate 2)) (BindF [1,2,3])
BindF {runBindF = [1,1,2,2,3,3]}
类似的例子可以写成,例如,(<*>)就Static类别而言。至于($),它是 中恒等函子的箭头映射(->),因此它仅fmap适用于Identity没有Identity包装器(参见 Daniel Wagner 对问题的评论)。