函子对于 (a -> b) -> (fa -> fb),是什么 (Category c) =>驾驶室-> c(fa)(fb)?
我想要一个函数,用于将纯函数映射到容器或通过它对应用/单子操作进行排序。对于纯映射,我们有
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您要求“某个 X 类”,但应该很清楚,此类的最(或者可能是唯一)正确的名称是“Functor”。您想要的只是为任意
Category
实例定义的仿函数类,而不是仅限于(->)
。当然,您的定义仍然仅限于从类别到由提供实例的类型构造函数定义的子类别的(内)函子。如果您进一步概括一下,这两个类别没有理由相同,从而为您提供 一个类型类就像这个:
与范畴论中函子的完整概念相比,这仍然是非常有限的,但是哦,好吧。
有趣的是,它仍然有一个
(->)
类型构造函数 - 这是因为,即使我们使用任意实例对源类别和目标类别进行建模,整个事物( (特别是函子本身)在某种意义上仍然存在于 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:
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 constructorf
.