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/