在尝试熟悉Control.Arrow时,我注意到Kleisli newtype似乎可以接受一个Functor实例,类似于:
instance Monad m => Functor (Kleisli m a) where
fmap f (Kleisli k) = Kleisli $ liftM f . k
为什么没有提供这个实例?它作为孤立实例存在于某个包中吗?
在尝试熟悉Control.Arrow时,我注意到Kleisli newtype似乎可以接受一个Functor实例,类似于:
instance Monad m => Functor (Kleisli m a) where
fmap f (Kleisli k) = Kleisli $ liftM f . k
为什么没有提供这个实例?它作为孤立实例存在于某个包中吗?
fmap f a = a >>> arr f
Functor
需要* -> *
,而Arrow
需要* -> * -> *
),所以不可能声明Functor
为Arrow
的超类。因此,每个箭头需要单独定义实例。ArrowMonad
包装任何箭头,然后给出一个Applicative
实例(因此也是一个Functor
):instance Arrow a => Applicative (ArrowMonad a) where ...
。Kleisli
缺少Functor
实例有任何特别的原因。最有可能的原因似乎是您不需要它。如果您想使用函子(或应用程序或单调)操作,则在原始单调值上执行操作。只有当您需要箭头界面时才将单调值包装到Kleisli
中。instance (Monad m) => Functor (Kleisli m a) where fmap = (^<<)
。或者建议在Haskell libraries中添加Functor
实例。 - Petr更新
在Control.Arrow
中已经定义:
(>>^) :: Arrow a => a b c -> (c -> d) -> a b d
(^<<) :: Arrow a => (c -> d) -> a b c -> a b d
更新2
如果你希望将Free
Monad插入到Kleisli
中,那是不可能的,因为Free
有一个额外的参数f
。
所以你需要使用Arrow Transformer
或者创建一个新的Arrow
类,例如:
class Arrow a => ArrowFunctor f a | a -> f where
afmap :: a b (f c)
软件包 arrows包含一些示例,但它没有实现Free
newtype FKleisli f m a b = FKleisli { runFKleisli :: a -> m (f b) }
,最后添加 instance (Functor f, Monad m, MonadFree f m) => ArrowFunctor (FKleisli f m a) where ...
。 - wit