我知道Arrow是一个Profunctor,可以在其中转换输入和输出,但可以在上映射一个Functor吗?
据我所知,答案是"没有",因为fmap
功能类型签名是(a -> b) -> f a -> f b
而且不承认Arrow a b
,但我希望我问的问题很清楚。
我正在寻找一种方法,例如,使用箭头转换Maybe
输入,Nothing
转到Nothing
,Just x
转到{{1}其中Just y
是将箭头应用于y
的结果。
答案 0 :(得分:7)
Arrow
结合了两个概念。正如你所说,其中一个就是一个profunctor,但首先它只是一个特定类别的类别(实际上是超类证据)。
这与此问题高度相关:是的,fmap
的签名是(a -> b) -> f a -> f b
,但实际上这几乎不是一个仿函数可以做到的完全一般性!在数学中,仿函数是两个类别 C 和 D 之间的映射,它将 C 中的每个箭头分配给 D中的箭头。不同类别的箭头,就是这样!标准Functor
类仅捕获最简单的特殊情况,即 Hask 类别中的endofunctors。
仿函数类的完整通用版本实际上看起来更像这样(这里是我的版本from constrained-categories):
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)
或者,在伪语法中,
class (Category (──>), Category (~>)) => Functor f (──>) (~>) where
fmap :: (a ──> b) -> f a ~> f b
当其中一个类别是正确的箭头而不是普通的功能类别时,这肯定也可以工作。例如,您可以定义
instance Functor Maybe (Kleisli [] (->)) (Kleisli [] (->)) where
fmap (Kleisli f) = Kleisli mf
where mf Nothing = [Nothing]
mf (Just a) = Just <$> f a
像
一样使用> runKleisli (fmap . Kleisli $ \i -> [0..i]) $ Nothing
[Nothing]
> runKleisli (fmap . Kleisli $ \i -> [0..i]) $ Just 4
[Just 0,Just 1,Just 2,Just 3,Just 4]
如果使用标准的profunctor-ish箭头,不确定这对于任何非常重要的事情是否有用。它绝对适用于不 Hask -profunctors,for instance
的其他类别instance (TensorSpace v) => Functor (Tensor s v) (LinearFunction s) (LinearFunction s)
表示你可以在张量积的单个因子上映射线性函数(而通常不可能在这样的产品上映射非线性函数 - 结果将取决于选择基于矢量空间)。
答案 1 :(得分:4)
我正在寻找一种方法,例如,使用箭头转换
Maybe
输入,Nothing
转到Nothing
,Just x
转到{{1}其中Just y
是将箭头应用于y
的结果。
这可以针对特定的x
实施(例如Functor
),但可能需要Maybe
:
ArrowChoice
有关用proc-notation编写的类似函数,请参阅Arrow equivalent of mapM?。
说到maybeAmap :: ArrowChoice p => p a b -> p (Maybe a) (Maybe b)
maybeAmap p =
maybe (Left ()) Right
^>> returnA +++ p
>>^ const Nothing ||| Just
, profunctors 有an interesting class called Traversing
:
mapM
-- Abbreviated class definition:
class (Choice p, Strong p) => Traversing p where
traverse' :: Traversable f => p a b -> p (f a) (f b)
wander :: (forall f. Applicative f => (a -> f b) -> s -> f t) -> p a b -> p s t
的旗标实例是Star
profunctor的实例,它提供了熟悉的Traversing
函数的替代编码。请注意,虽然leftaroundabout's answer演示了非 Hask 仿函数,但类别不一定是 Hask -profunctors,而traverse
我们有一个构造Traversing
不一定有Profunctor
个实例。