函子对于 (a -> b) -> (fa -> fb),是什么 (Category c) =>驾驶室-> c(fa)(fb)?

发布于 2024-11-16 20:31:55 字数 1653 浏览 4 评论 0原文

我想要一个函数,用于将纯函数映射到容器或通过它对应用/单子操作进行排序。对于纯映射,我们有

fmap :: Functor f => (a -> b) -> (f a -> f b)

对于一元排序,我们有(来自 Data.Taversable)

mapM :: (Traversable f, Monad m) => (a -> m b) -> (f a -> m (f b))

这类似于

mapKleisli :: (Traversable f, Monad m) => Kleisli m a b -> Kleisli m (f a) (f b)
mapKleisli = Kleisli . mapM . runKleisli

我们知道 (->) 和 (Kleisli m) 都是类别(和箭头)。所以很自然地做一个概括:

mapCategory :: (X f, Category c) => c a b -> c (f a) (f b)

你知道这样一个具有类似方法的类X吗?也许,在黑客攻击的某个地方?我尝试 hoogle/hayoo 但没有找到合适的东西。

更新:

现在我更知道我需要什么了。 Kleisli 箭头和 (->) 都是 ArrowApply 的实例,它与 Monad 一样强大。我想出了这个基于箭头的 Travesable 版本:

{-# LANGUAGE TypeOperators #-}

import Prelude hiding (id, (.), mapM)
import Control.Arrow
import Control.Category

class Traversable f where
  traverse :: ArrowApply (~>) => f a -> (a ~> b) ~> f b

mapArrow :: (ArrowApply (~>), Traversable f) => a ~> b -> f a ~> f b
mapArrow a = arr (\x -> (traverse x, a)) >>> app

instance Traversable Maybe where
  traverse Nothing = arr (const Nothing)
  traverse (Just x) = arr (\a -> (a, x)) >>> app >>> arr Just

instance Traversable [] where
  traverse [] = arr (const [])
  traverse (x : xs) = undefined -- this is hard!

我可以使用通常的基于 Applicative 的 Traversable,并使用 Identity 来表示纯函数,但我不确定它是否好。将纯函数视为一元操作的特例是很奇怪的。将纯函数和一元操作解释为某个操作类(Category/Arrow/ArrowApply)的实例对我来说看起来更直接。

问题:您想完成 [] 的实例吗?我对 ArrowApply 与 Monad 的看法有道理吗?

I would like to have a function for either mapping a pure function to a container or sequencing applicative/monadic action through it. For pure mapping we have

fmap :: Functor f => (a -> b) -> (f a -> f b)

For monadic sequencing we have (from Data.Taversable)

mapM :: (Traversable f, Monad m) => (a -> m b) -> (f a -> m (f b))

Which is similar to

mapKleisli :: (Traversable f, Monad m) => Kleisli m a b -> Kleisli m (f a) (f b)
mapKleisli = Kleisli . mapM . runKleisli

We know both (->) and (Kleisli m) are categories (and arrows). So it's naturally to make a generalization:

mapCategory :: (X f, Category c) => c a b -> c (f a) (f b)

Do you know such a class X with similar method? Maybe, somewhere on hackage? I tried to hoogle/hayoo but haven't found anything appropriate.

Update:

Now I know better what I need. Both Kleisli arrows and (->) are instances of ArrowApply which is as powerful as Monad. I came up with this arrow-based version of Travesable:

{-# LANGUAGE TypeOperators #-}

import Prelude hiding (id, (.), mapM)
import Control.Arrow
import Control.Category

class Traversable f where
  traverse :: ArrowApply (~>) => f a -> (a ~> b) ~> f b

mapArrow :: (ArrowApply (~>), Traversable f) => a ~> b -> f a ~> f b
mapArrow a = arr (\x -> (traverse x, a)) >>> app

instance Traversable Maybe where
  traverse Nothing = arr (const Nothing)
  traverse (Just x) = arr (\a -> (a, x)) >>> app >>> arr Just

instance Traversable [] where
  traverse [] = arr (const [])
  traverse (x : xs) = undefined -- this is hard!

I could use just usual Applicative-based Traversable, with Identity for pure functions, but I'm not sure it is good. Considering pure functions as special case of monadic actions is weird. Interpreting both pure functions and monadic actions as instances of some action class (Category/Arrow/ArrowApply) looks more straightforward to me.

Questions: would you like to finish instance for []? Has my opinion about ArrowApply vs Monad any sense?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

眼波传意 2024-11-23 20:31:55

您要求“某个 X 类”,但应该很清楚,此类的最(或者可能是唯一)正确的名称是“Functor”。您想要的只是为任意 Category 实例定义的仿函数类,而不是仅限于 (->)

当然,您的定义仍然仅限于从类别到由提供实例的类型构造函数定义的子类别的(内)函子。如果您进一步概括一下,这两个类别没有理由相同,从而为您提供 一个类型类就像这个:

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)

与范畴论中函子的完整概念相比,这仍然是非常有限的,但是哦,好吧。

有趣的是,它仍然有一个 (->) 类型构造函数 - 这是因为,即使我们使用任意实例对源类别和目标类别进行建模,整个事物( (特别是函子本身)在某种意义上仍然存在于 Hask 中,即与 (->) 关联的类别。粗略地说,仿函数的另一半(映射对象的部分)是 * -> 类型中的 (->)。 * 为类型构造函数 f

You're asking for "some class X", but it should be pretty clear that the most (or perhaps, only) correct name for this class would be "Functor". What you want is simply a functor class defined for an arbitrary Category instance, rather than limited to (->).

Of course, your definition is still limited to (endo)functors from a category to a subcategory defined by the type constructor giving the instance. If you generalize a bit further, there's no reason for the two categories to be the same, giving you a type class something like this one:

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)

This is still awfully limited vs. the full concept of a functor in category theory, but oh well.

It's also interesting to observe that this still has a (->) type constructor in it--that's because, even though we're modeling the source and target categories with arbitrary instances, the whole thing (and in particular, the functor itself) still exists in some sense in Hask, i.e., the category associated with (->). The other half of the functor (the part mapping objects) is, roughly speaking, the (->) in the kind * -> * for the type constructor f.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文