你的两个例子都是函子的箭头映射(不是Functors
,而是更广泛分类意义上的函子),就像fmap
a 的箭头映射一样Functor
。(=<<)
,例如,是某个 monad的函子从Kleisli m
到的箭头映射。因此,适当的概括是解释不同类别之间的函子的概括。规定:(->)
m
Control.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 对问题的评论)。