Haskell 为什么静态箭头概括为箭头?
众所周知,Haskell 为什么静态箭头概括为箭头?,haskell,applicative,category-theory,arrows,Haskell,Applicative,Category Theory,Arrows,众所周知,Applicative概括了箭头。Sam Lindley、Philip Wadler和Jeremy Yallop在论文中指出,Applicative等同于静态箭头,即具有以下同构的箭头: arrab::arr()(a->b) 据我所知,可以用以下方式来说明: 注意:newtype Identity a=Id{runId::a} Klesli Identity是一个静态箭头,它包装了k::a->Identity b。同构只是移除或添加包装器 Kleilsi可能不是一个静态箭头,因为k=K
Applicative
概括了箭头
。Sam Lindley、Philip Wadler和Jeremy Yallop在论文中指出,Applicative
等同于静态箭头,即具有以下同构的箭头:
arrab::arr()(a->b)
据我所知,可以用以下方式来说明:
注意:newtype Identity a=Id{runId::a}
Klesli Identity
是一个静态箭头,它包装了k::a->Identity b
。同构只是移除或添加包装器
Kleilsi可能
不是一个静态箭头,因为k=Kleisli(const Nothing)
存在-所有f::a->b
s只对应于。f
,同构中没有k
的位置
但同时Kleisli标识
和Kleisli可能
都是Arrow
实例。因此,我看不出这种概括是如何运作的
此外,他们还:
这两个概念通常分别称为静态箭头和Kleisli箭头。由于使用“箭头”这个词有两种微妙的不同含义,这会使本文令人非常困惑,因此我们选择了“态射”,这是这个替代含义的同义词
这是目前为止我唯一的线索——我是否混淆了HaskellArrow
和arrows
那么,这个层次结构是如何工作的呢?这一应用性属性是如何正式化/证明的?我相信“泛化”这个词会让你误入歧途。如果k
是箭头
,则实际情况如下:
kx
对于任何x
都将是一个应用程序
李>
- 特别是,
k()
将是一个应用程序李>
- 然后,该应用程序可以作为一个等效的静态箭头响应(就、
static(k())a b~k()(a->b)
)
然而,这个过程在一般情况下并不是无损的:静态箭头static(k())
不一定等同于我们开始使用的k
箭头;不必存在同构。换句话说,静态箭头不能概括箭头。如果我们要定义一个StaticArrow
类,它将是Arrow
的子类,而不是超类
附言:在维基百科的引文中,措辞只是强调的问题。例如,虽然克莱斯利箭头确实是休斯/Control.Arrow
Arrow,但大多数时候,当人们谈论“克莱斯利箭头”时,他们并不是在思考Arrow
的例子,而仅仅是在一个范畴中它们是怎样的态射,在这个范畴中,某些单子的范畴法则相当于单子法则。特别是,这就足以在维基书的段落中讨论讨论。它认为混淆是你可以考虑<代码> KLASLI可能是< /Cord>在适当的类别中的静态箭头。代码>arra(可能b)::arr()(a->Maybe b)
@chepner你能不能,请给出一个非静态箭头的例子?arra(fb)
其中我认为f
不是内函子。你不能定义一个不使用Haskell类型的箭头,所以任何涉及的函子都是Hask上的内函子。(但我只是猜测,如果这不明显的话。)谢谢你的回答。说实话,我有点迷路了。据我所知,Applicative
在将functor中的函数应用于functor中的值之前运行所有效果。因此,我们不能编写一个函数,它用getLine
获取一行,然后将其打印回来。然而,Category
接口允许这样的事情。那么,StaticArrow
怎么可能是Category
的子类呢?而Applicative
无法在应用程序中运行效果的想法是如何正式化的?@zhiltsofigor“然而,Category
接口允许这样的事情”——允许,而不是强制。就像有Arrow
实例不是ArrowApply
实例一样(或者,就此而言,有Category
实例不是Arrow
实例),也有Arrow
实例不是与某个静态箭头同构的,因此,这不是我们假设的StaticArrow
类的一个实例。因此,“习语是不经意的,…”首页上的staticarrows->arrows
基本上意味着任何StaticArrow
都会产生arrow
,而不会丢失任何信息?[1/2]@zhiltsofigor(1)第一页图表中从左到右的箭头表示另一种含义,即“静态箭头的等式嵌入到箭头演算中”(第15页)。非正式地说,这意味着箭头至少具有静态箭头的所有操作。注意,本文还表明,静态箭头可以通过向箭头添加额外的操作(“带延迟的经典箭头”)来获得;既然如此,添加这样一个操作实际上会削弱抽象的事实可能有点令人惊讶。[2/2]@ZhiltsoffIgor(2)在您的编辑中:arr
可以将任意函数提升到箭头,因此以这种方式使用它并不能告诉我们箭头组合本身允许什么。箭头法则之一是arr(g.f)=arr g=print))
,因此箭头实际上并没有处理IO
效果。与之相比,例如,Kleisli(const getLine)>>>Kleisli print::Kleisli IO a()
,其中效果的排序实际上是通过(>>)
完成的。