如何为 Arrows 写下顺序?

How could sequence be written down for Arrows?

sequenceA是一个众所周知的函数:

sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)

我想知道我们是否可以为箭写下类似的东西。不幸的是,我没有设法实现以下内容:

sequenceArr :: (Traversable t, Arrow a) => t (a b c) -> a b (t c)

据我了解,Applicative概括了Arrow,因此,我们应该可以写下来。我是为列表做的:

sequenceArrLst :: Arrow a => [a b c] -> a b [c]
sequenceArrLst t = let t' = (>>> arr (: [])) <$> t
                   in foldr1 (\f g -> f &&& g >>> arr (uncurry (++))) t'

然而,正如您所注意到的,我们并没有摆脱列表中的a b层,而是将结果包装到一个新列表中。那么,我们怎样才能真正去掉a b层呢?我应该注意到,在 this question, duplode 下的评论中指出:

...between (.), id, arr and first, there isn't anything that allows collapsing two a r layers into one.

如果他们是对的,我们需要 ArrowApply 吗?老实说,我写下来了,还是没能去掉里面的箭头t:

sequenceArrApp :: (Functor f, ArrowApply a) => f (a b c) -> a b (f (a () c))
sequenceArrApp t = arr $ \ b -> (\ f -> arr (\ () -> (f, b)) >>> app) <$> t

是否可以调整此代码段以使其缺少 a () 层?

所以,我的问题是:

  1. sequenceArr :: (Traversable t, Arrow a) => t (a b c) -> a b (t c) - 我们可以写下来吗?如果是,怎么做?
  2. 有什么方法可以去除 a b 层 (Arrow a)。如果是这样,为什么当我们写下 join for Arrow 时它们不起作用(如果它们实际上不起作用)?
  3. 我们需要 ArrowApply 吗?如果是这样,如何?能否调整我的变体以获得此结果:sequenceArr :: (Traversable t, ArrowApply a) => t (a b c) -> a b (t c)?

As far as I understand, Applicative generalizes Arrow, thus, we should be able to write this down.

请记住,这里的“泛化”实际上意味着“如果我们确定 Arrow 的输入类型参数,生成的 * -> * 类型构造函数将是 Applicative” ,您最初提出的 sequenceArr 相当于 sequenceA 专门用于可以以这种方式从箭头中挤出的应用程序。由于这些应用程序可以通过 the WrappedArrow newtype 表示,因此一种可能的定义是:

sequenceArr :: (Traversable t, Arrow a) => t (a b c) -> a b (t c)
sequenceArr = unwrapArrow . sequenceA . fmap WrapArrow

查看 WrappedArrow 如何实例化 Applicative...

instance Arrow a => Applicative (WrappedArrow a b) where
    pure x = WrapArrow (arr (const x))
    liftA2 f (WrapArrow u) (WrapArrow v) =
      WrapArrow (u &&& v >>> arr (uncurry f))

... 应确认此实现在精神上与您尝试编写 sequenceArrLst.

一致

(注意这个 sequenceArr 确实与 traverse' from Data.Profunctors.Traversing that dfeuer 非常不同。traverse' 不是 sequenceA 的特化,而是对 traverse 的概括,所以可以说,一个完全不同的维度。)