我花了一段时间学习和搜索了Arrows,但对Arrow类的必要性感到有些困惑。据我所知,Arrow类是函数的抽象,而ArrowA a b c
表示某种东西需要b类型的输入和c类型的输出。此外,它提供了像一些基本的操作>>>
,arr
和first
。
但是,我找不到type的标准函数和type的b -> c
Arrow之间的任何区别A a b c
。在我看来,first
并>>>
可以通过更换\(b, c) -> (f b, c)
,和(.)
。另外,由于箭头内部的每个计算都由函数表示,因此如果我们用这些函数替换箭头,我认为不会有任何区别。
简而言之,我认为Arrows计算图的每个节点(类似于https://www.haskell.org/arrows/syntax.html中的节点)都可以由Haskell的标准函数代替。如果是真的,为什么我们使用Arrow而不是函数?
遵循某些定律的抽象使您可以进行通用编程。您可以在没有任何类型类的情况下进行编程(没有monad,应用程序,没有等式/顺序等),但这将非常不便,因为您将无法编写利用这些属性的通用代码。
就像您说不想使用该Ord
实例一样,然后您必须为Set
可以订购的每种数据类型分别重写实现。
的要点Arrow
是描述计算
因此,箭头A b c
不是函数a -> b
。箭头最有可能在内部作为一种功能实现,但更为复杂,实现该Arrow
界面的目的是(除其他外)描述它们的组成方式。
专门针对箭头,您可以使用箭头符号来对任何有效的使用相同的符号Arrow
。举个例子,在netwire包中,Wire
数据类型实现了Arrow
,因此您可以使用箭头符号,以及在箭头上起作用的所有实用程序功能。没有实例,您将必须具有特定于netwire的语法,或者仅使用netwire提供的功能。
举个例子:与State
monad对应的箭头是a -> s -> (b, s)
。但是两个这样的函数不能用组合(.)
。您需要描述它们的组成,而事实恰恰是Arrow
这样。
更新:可能存在多种可组合性概念,但我想您的意思是类似函数的组合。是的,这种可组合性来自Arrow
的Category
超类,该超类定义了身份和组成。
我最近从中了解到,另一部分Arrow
来自于Strong
发音器。发音器和箭头之间的关系是什么?(尽管在type-class层次结构中未捕获到该值,因为Profunctor
typeclass比年龄年轻Arrow
)。Profunctors允许由纯计算从“双方”改性,见lmap
/ rmap
/dimap
在Profunctor
。对于箭头,我们有(<<^)
和(^>>)
,用arr
和>>>
通过将bv左右的箭头与用构造的纯箭头组成arr
。
最后箭的力量为wrt (,)
,被俘获first :: Arrow a => a b c -> a (b, d) (c, d)
。这意味着我们只能在输入的一部分上使用箭头,而传递另一个不变的箭头。这样就可以用“平行线”构造“电路”,而不必first
保存一部分计算的输出并在以后的某个地方使用它。
一个好的练习是绘制一个表示计算的电路,然后尝试使用Arrow
基元/实用工具或使用箭头语法表示法来表示它。您会看到first
(或***
)对于此至关重要。
有关操作的详细说明,请参见“箭头可以多任务处理”。
对于更多的理论背景,“箭是坚强的Monads”可能很有趣(我还没有读过)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句