【问题标题】:Issues Generalising Functor泛化函子的问题
【发布时间】:2015-09-21 21:14:02
【问题描述】:

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 实例,如下所示(没有丑陋的 Identity 包装器):

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

哪个好。

现在,我可以立即确定一个问题,即对于给定的 rt 参数到 Functor,原始类定义允许 f 有多个选项,而根据我的定义,@987654341 @ 和 t 确定 f。这是一个严重的问题,好像我定义说:

fmap :: (a -> b) -> (Maybe a -> Maybe b)

我无法定义:

fmap :: (a -> b) -> ([a] -> [b])

在这两种情况下,r = (->)t = (->)。所以目前我的Functor 甚至没有替换原来的 Prelude 版本。

所以我现在有一些问题:

  1. 我可以调整我的定义,使rt 不能确定f(与原始版本一样)吗?或者这是否需要Injective Type Families(如果是这种情况,我很乐意编译头部来尝试这个)。
  2. 我能否进一步调整我的定义,使fr 确定t 以及ft 确定r
  3. 执行上述操作后(如果不可能,则不执行)对类型推断有哪些潜在影响?
  4. 与原来的相比,我的类定义是否还有其他不好的地方,比如增加打字?
  5. 是否有任何替代方法仍然允许我定义 Kleisli 函子而不用 Identity 包装,同时比我提出的“更好”(更有用的结构、更好的类型推断等)。

很抱歉,最后几个问题有点含糊,我知道类型推断与一般性通常是一种权衡,但我只是在这个特殊情况下寻找一些想法。

(这个问题部分来自对this question的回答)

【问题讨论】:

    标签: haskell functor category-theory


    【解决方案1】:

    你能得到的最接近的应该是

    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
    

    【讨论】:

    • 我很想将class .. => Functor (f :: k) ...PolyKinds 一起使用,并删除下面出现的()。这是否是一个好主意,我不能 100% 确定。
    • @chi 我考虑过自己写,但我对 PolyKinds 不是很坚定。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多