问题
While trying to familiarize myself with Control.Arrow, I have noticed that the Kleisli newtype would seem to admit a Functor instance, something like:
instance Monad m => Functor (Kleisli m a) where
fmap f (Kleisli k) = Kleisli $ liftM f . k
Is there a reason why this instance isn't provided? Does it exist in some package as an orphan instance?
回答1:
Every arrow can be made into a valid Functor
by defining
fmap f a = a >>> arr f
However it's not possible to declare a Functor
to be a superclass of Arrow
because of their different kinds (Functor
needs * -> *
while Arrow
needs * -> * -> *
). So every arrow needs to define the instance separately.
You can wrap any arrow with ArrowMonad
, which then gives an Applicative
instance (and therefore also a Functor
): instance Arrow a => Applicative (ArrowMonad a) where ...
.
I don't see any particular reason why Kleisli
lacks the Functor
instance. The most probable seems to be that you don't need it. If you want to use functorial (or applicative or monadic) operations, you do it on the original monad. You only wrap the monad into Kleisli
when you need the arrow interface.
回答2:
UPDATE
in Control.Arrow
is already defined:
(>>^) :: Arrow a => a b c -> (c -> d) -> a b d
(^<<) :: Arrow a => (c -> d) -> a b c -> a b d
UPDATE 2
If you wish to insert Free
Monad into Kleisli
- it is impossible, Free
has one extra parameter f
.
So you need to use Arrow Transformer
or create a new Arrow
class, like
class Arrow a => ArrowFunctor f a | a -> f where
afmap :: a b (f c)
Package arrows consist some examples, but it not implement Free
来源:https://stackoverflow.com/questions/18925045/why-there-isnt-a-functor-instance-for-kleisli-in-control-arrow