为什么相互让步使得 ArrowApply 和 Monads 等价,不像 Arrow 和 Applicative?
Why does mutual yielding make ArrowApply and Monads equivalent, unlike Arrow and Applicative?
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 referenced above, I felt that this snippet was a plausible proof for the equivalence of ArrowApply
and Monad
classes. Yet, having the knowledge that 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
class 实际上已经比 arr
更严格了 –它给你一个来自 Hask 的仿函数到类别中。但是,有点令人惊讶的是,这还需要您在 other 方向上进行映射:任何箭头都可以用 function 替换,它只会产生一个普通域的箭头。具体来说,
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 箭头。
查看其他一些范畴论层次结构,发现这不是笛卡尔幺半群范畴的基本特征,而是Hask[的产物] =43=] → k 函子。例如。 in constrained-categories 我已经非常接近标准 classes,PreArrow
作为笛卡尔幺半群类别的 class,但故意将 arr
排除在外并且没有不要让它特定于 Hask,因为这会使类别的功能变得过于愚蠢并导致它几乎等同于 Hask-克莱斯利
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 referenced above, I felt that this snippet was a plausible proof for the equivalence of ArrowApply
and Monad
classes. Yet, having the knowledge that 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
class 实际上已经比 arr
更严格了 –它给你一个来自 Hask 的仿函数到类别中。但是,有点令人惊讶的是,这还需要您在 other 方向上进行映射:任何箭头都可以用 function 替换,它只会产生一个普通域的箭头。具体来说,
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 箭头。
查看其他一些范畴论层次结构,发现这不是笛卡尔幺半群范畴的基本特征,而是Hask[的产物] =43=] → k 函子。例如。 in constrained-categories 我已经非常接近标准 classes,PreArrow
作为笛卡尔幺半群类别的 class,但故意将 arr
排除在外并且没有不要让它特定于 Hask,因为这会使类别的功能变得过于愚蠢并导致它几乎等同于 Hask-克莱斯利