Functor in 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)
但是我想说我想要一个从普通函数到Kleisli箭头的仿函数(这可能是一个愚蠢的例子)。
我想要一个这样的类型:
fmap :: (Monad m) => (a -> b) -> Kleisli m a b
我可以让r = (->)
,t = Kleisli m
获取:
fmap :: (Monad m) => (a -> b) -> Kleisli m (f a) (f b)
但是,那是什么f
?!我真的只是希望它消失。我可以通过f = Identity
来使用Identity仿函数,但后来我得到了:
fmap :: (Monad m) => (a -> b) -> Kleisli m (Identity a) (Identity b)
这需要一些杂乱的解包。
然后我想到像这样定义Functor:
class (Category r, Category t) => Functor r t where
type family F r t x :: *
fmap :: r a b -> t (F r t a) (F r t b)
这允许我为Kleisli定义一个Functor实例,如下所示(没有丑陋的身份包装器):
instance (Monad m) => Functor (->) (Kleisli m) where
type F (->) (Kleisli m) a = a
fmap f = Kleisli (return . f)
在此之后,我很确定我在:
fmap :: (Monad m) => (a -> b) -> Kleisli m a b
哪个好。
现在,我可以立即识别出一个问题,即,对于r
的给定t
和Functor
参数,原始类定义允许f
的多个选项,而根据我的定义,r
和t
决定f
。这是一个严重的问题,好像我定义说:
fmap :: (a -> b) -> (Maybe a -> Maybe b)
我无法定义:
fmap :: (a -> b) -> ([a] -> [b])
与两种情况一样,r = (->)
和t = (->)
。所以目前我的Functor
甚至没有取代原来的Prelude版本。
所以我现在有一些问题:
r
和t
不会确定f
(与原始版本一样)吗?或者这需要Injective Type Families(如果是这种情况,我很乐意编译头来尝试这个)。 f
和r
确定t
以及f
和t
确定r
?对不起,最后几个问题有点模糊,我知道类型推断与普遍性通常是一种权衡,但我只是在这个特殊情况下寻找一些想法。
(这个问题部分来自对this question)
的回答答案 0 :(得分:3)
你能得到的最接近的是
class (Category r, Category t) => Functor
(f :: *) (r :: *->*->*) (t :: *->*->*) where
type F f x :: *
fmap :: Tagged f ( r a b -> t (F f a) (F f b) )
instance Functor [()] (->) (->) where
type F [()] x = [x]
fmap = Tagged map
instance (Monad m) => Functor (Kleisli m () ()) (->) (Kleisli m) where
type F (Kleisli m () ()) x = x
fmap = Tagged $ \f -> Kleisli $ return . f