在monad上映射箭头

时间:2017-04-15 21:42:59

标签: haskell arrows

我知道Arrow是一个Profunctor,可以在其中转换输入和输出,但可以在上映射一个Functor吗?

据我所知,答案是"没有",因为fmap功能类型签名是(a -> b) -> f a -> f b而且不承认Arrow a b,但我希望我问的问题很清楚。

我正在寻找一种方法,例如,使用箭头转换Maybe输入,Nothing转到NothingJust x转到{{1}其中Just y是将箭头应用于y的结果。

2 个答案:

答案 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转到NothingJust 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个实例。