为什么 ArrowApply 在证明与 Monads 等价时是唯一的选择?

Why is ArrowApply an only option when proving equivalence with Monads?

, leftarounabout left 为什么我们 实际上 认为 ArrowApplyMonad 等价。

想法是在往返过程中不丢失任何信息:

arrAsFunction :: Arrow k => k x y -> (x -> k () y)
arrAsFunction φ x = φ <<< arr (const x)

retrieveArrowFromFunction :: ∀ k x y .
          ArrowApply k => (x -> k () y) -> k x y
retrieveArrowFromFunction f = arr f' >>> app
 where f' :: x -> (k () y, ())
       f' x = (f x, ())

我(可能)明白,为什么我们开始谈论 (x -> k () y) - 一个包裹的 \ ~() -> ... 并不能造出一支好箭,因此我们希望它取决于环境。

我的问题是:我们如何确定以下函数不存在:

retrieveArrowFromFunction :: ∀ k x y .
          Arrow k => (x -> k () y) -> k x y

我试着想出一些箭头,这些箭头会弄乱该类型的 Curry-Howard 对应关系。这是正确的引导吗?可以更简单地完成吗?

这是一个非常简单的箭头。你可能会认为它是幺半群 Any.

上的一个类似 Writer 的箭头
newtype K a b = K Bool

instance Category K where
    id = K False
    K x . K y = K (x || y)

instance Arrow K where
    arr _ = K False
    K x *** K y = K (x || y)

如果您仔细研究这些定义的结果,您会发现 firstsecond 更改箭头的类型而不更改包含的 Bool。这意味着我们无法创建合法的 ArrowApply 实例。下面的规律决定了我们必须选择app = K False

first (arr (...)) >>> app = id

但是下面的规律,选择g = K True,决定我们必须选择app = K True

first (arr (...)) >>> app = second g >>> app

自相矛盾。

将此观察提升到您的直接问题,我们无法定义

retrieve :: (x -> K () y) -> K x y

以不丢失信息的方式。事实上,我们甚至不能定义更单态(因此更容易实现)的函数

retrieveMono :: (Bool -> K () ()) -> K Bool ()

以一种不丢失信息的方式:参数类型有 4 个居民,而 return 类型只有 2 个。

附录

你可能想知道我是怎么想出这个反例的。在我看来,问题的核心是是否有 Arrow 而不是 ArrowApply。我记得约翰·休斯 (John Hughes) 撰写的第一篇关于箭头的论文 Generalising Monads to Arrows 有一个激励性的例子,它不能成为 monad(因此也不能是 ArrowApply 实例) .我翻了论文,回顾了解析箭头的定义,并将其归结为不可能变成 ArrowApply 或 monad 的本质:我扔掉了箭头的类函数部分,观察到它的其余部分充当了一个花式类型的幺半群,并选择了我能想到的最简单的非平凡幺半群来代替论文中令人兴奋的幺半群。