为什么相互屈服使得ArrowApply和Monads等同,不同于Arrow和Applicative?

问题描述 投票:8回答:1

这是我要参考的SO帖子。. 另外,为了不把材料分开,我在那道题中使用了和上边一样的片段。.

它是 众所周知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))

直到我偶然发现... 岗位 上面提到的,我觉得这个片段是一个合理的证明,证明了等价的 ArrowApplyMonad 类。然而,在知道 箭头和应用型其实并不等同。 和下面的片段让我对等价物的完整证明产生了好奇。MonadArrowApply:

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

>因此,如果你通过applicative进行往返,你会失去一些功能。如果提供的例子是显而易见的,但是我不明白为什么通过Monad的 "往返 "会保留所有ArrowApply的功能,因为最初我们有一个箭头,它依赖于一些输入(a b c),但最终,我们会将一个箭头强行放入一个以单元类型为输入类型的包装器中(ArrowMonad (a () b)).

很明显,我在这里做了一件非常错误的事情,然而我却无法理解到底是什么。

什么是充分证明 ArrowApplyMonad 是等价的?

不等价的例子有哪些?ArrowApplicative 占?一个人是否能概括另一个人?

在箭头微积分和范畴理论中,对整个情况的解释是什么?

我既希望得到完整的解释,也希望得到可以帮助自己起草一份合理的证明的提示。

haskell monads applicative category-theory arrows
1个回答
3
投票

由于最初我们有一个箭头,它取决于一些输入(a b c),但最终,我们会将一个箭头强行放入一个以单元类型为输入类型的包装器中(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 漏斗。例如 在约束类别中 我严格按照标准班级,以 PreArrow 作为卡提斯一元类,但刻意保留了 "卡提斯一元类"。arr 出,并没有将其具体化为。哈斯克因为那会使该类别的能力过于淡化,导致它几乎等同于 哈斯克-Kleisli。

© www.soinside.com 2019 - 2024. All rights reserved.