haskell - 与 Arrow 和 Applicative 不同,为什么互让让 ArrowApply 和 Monads 等价?

标签 haskell monads applicative category-theory arrows

Here's the SO post I'm going to refer to . Also, I'm going to use the same snippets as the OP in that question in order not to separate the materials .
widely known那个ArrowApply实例产生一个 Monad,反之亦然:

newtype ArrowMonad a b = ArrowMonad (a () b)

instance Arrow a => Functor (ArrowMonad a) where
    fmap f (ArrowMonad m) = ArrowMonad $ m >>> arr f

instance Arrow a => Applicative (ArrowMonad a) where
   pure x = ArrowMonad (arr (const x))
   ArrowMonad f <*> ArrowMonad x = ArrowMonad (f &&& x >>> arr (uncurry id))

instance ArrowApply a => Monad (ArrowMonad a) where
    ArrowMonad m >>= f = ArrowMonad $
        m >>> arr (\x -> let ArrowMonad h = f x in (h, ())) >>> app

newtype Kleisli m a b = Kleisli { runKleisli :: a -> m b }

instance Monad m => Category (Kleisli m) where
    id = Kleisli return
    (Kleisli f) . (Kleisli g) = Kleisli (\b -> g b >>= f)

instance Monad m => Arrow (Kleisli m) where
    arr f = Kleisli (return . f)
    first (Kleisli f) = Kleisli (\ ~(b,d) -> f b >>= \c -> return (c,d))
    second (Kleisli f) = Kleisli (\ ~(d,b) -> f b >>= \c -> return (d,c))
直到我偶然发现 post上面提到的,我觉得这个片段是 ArrowApply 等价的合理证据。和 Monad类。然而,知道Arrow and Applicative are not, in fact, equivalent下面的片段让我对 Monad 的完整等效证明感到好奇和 ArrowApply :
newtype Arrplicative arr o a = Arrplicative{ runArrplicative :: arr o a }

instance (Arrow arr) => Functor (Arrplicative arr o) where
    fmap f = Arrplicative . (arr f .) . runArrplicative

instance (Arrow arr) => Applicative (Arrplicative arr o) where
    pure = Arrplicative . arr . const

    Arrplicative af <*> Arrplicative ax = Arrplicative $
        arr (uncurry ($)) . (af &&& ax)

newtype Applicarrow f a b = Applicarrow{ runApplicarrow :: f (a -> b) }

instance (Applicative f) => Category (Applicarrow f) where
    id = Applicarrow $ pure id
    Applicarrow g . Applicarrow f = Applicarrow $ (.) <$> g <*> f

instance (Applicative f) => Arrow (Applicarrow f) where
    arr = Applicarrow . pure
    first (Applicarrow f) = Applicarrow $ first <$> f

Thus if you round trip through applicative you lose some features.


写下来的例子很明显,但是我无法理解通过 Monad 的“往返”如何保留所有 ArrowApply 功能,因为最初我们有一个取决于某些输入(a b c)的箭头,但最后,我们最终有一个箭头被强制进入以单元类型作为其输入类型 (ArrowMonad (a () b)) 的包装器中。
很明显,我在这里做错了什么,但我无法理解到底是什么。ArrowApply 的完整证明是什么?和 Monad是等价的吗?Arrow不等价的例子是什么和 Applicative占?一个人能概括另一个人吗?
箭头演算和范畴论对整个情况的解释是什么?
我将不胜感激完整的解释和提示,它们可以帮助人们自己制定一份似是而非的证据。

最佳答案

since initially we had an arrow which depends on some input (a b c) but in the end, we end up with an arrow forced into a wrapper which has unit type as its input type (ArrowMonad (a () b))



我想这是困惑的中心点,而且确实令人困惑。我喜欢认为箭头主要是笛卡尔幺半群中的态射,你不会得到这个,但已经 Arrow由于arr,类实际上比这更严格– 它给你一个来自 的仿函数哈斯克入类。但是,有点令人惊讶的是,这也需要你得到另一个方向的映射:任何箭头都可以替换为只产生一个平凡域箭头的函数。具体来说,
arrAsFunction :: Arrow k => k x y -> (x -> k () y)
arrAsFunction φ x = φ <<< arr (const x)

好吧,仅此一点就不会太开创性了——也许我们只是在这里丢弃了一些信息? – 但使用 ArrowApply这实际上是一个同构:您可以通过以下方式取回原始箭头
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, ())

...这正是 Monad (ArrowMonad a) 中使用的内容实例。

所以结果是:arr ,通过要求您可以在类别中嵌入任何 Haskell 函数,强制该类别基本上归结为带有一些结果包装器的函数,IOW 类似于 Kleisli 箭头。

查看其他一些类别理论层次结构,看看这不是笛卡尔幺半群类别的基本特征,而是 的真正产物。哈斯克 → k 仿函数。例如。 in constrained-categories我用 PreArrow 密切反射(reflect)了标准类。作为笛卡尔幺半群的类,但故意保留arr并没有使其特定于 哈斯克 ,因为这会使类别的功能变得过于笨拙,并导致它几乎等同于 哈斯克 -克莱斯利。

关于haskell - 与 Arrow 和 Applicative 不同,为什么互让让 ArrowApply 和 Monads 等价?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59869399/

相关文章:

Haskell 处理 [IO 字符串]

haskell - 无法为 Continuation Monad Transformer 派生 MonadWriter 的实例?

haskell - 我的程序图灵完备吗?

haskell - Monad定义中的类型错误

haskell - Applicative 中纯定义的问题

haskell - 从免费的替代仿函数生成 optparse-applicative 解析器

Haskell 执行顺序

haskell - 类似 curl 的单子(monad)变压器?

haskell - Haskell monad 不强制执行的分类单子(monad)的身份是什么?

haskell - 结合仿函数和单子(monad)