Arrows 是函数的真正概括吗?

Are Arrows a true generalization of functions?

箭头通常被描述为函数的泛化(仅静态生成的函数,即不支持部分应用程序/闭包)。但是,至少看一下在 Haskell 中建模的 Arrows,我看不出它们如何概括多个参数的函数 return 一个结果(通常可能不是一个结果元组)。我试图设想如何仅使用箭头界面就可以得到箭头的组合,从而产生一个通常可能不是元组的结果。有没有办法做到这一点,或者这是对 Arrow 类型功能的故意限制?

据我所知,箭头提供了组合静态(可能是并行的)管道的能力,但它们不能 'fold' 将输出的元组组合成单个最终结果。是我错了还是我遗漏了什么?

你可以想到type

的函数
f :: a -> b -> c

作为一个接受类型 a 的值并生成另一个类型 b -> c 的函数的函数。也就是说,

f :: a -> (b -> c)

箭头的概括非常简单:

f :: Arrow a (Arrow b c)

为了使用多个变量进行函数组合,您必须使用 (.) 运算符或 (<<<) 进行一些疯狂的语义操作。与 makes functions with multiple arguments pointfree cumbersome 阻碍语法以这种方式表示箭头的原因相同,这就是为什么有这么多组合器使用元组的原因。此外,没有什么能阻止您定义将元组映射到值的箭头。 arr函数把任意函数变成箭头!

f :: (a, b) -> c
af :: Arrow (a, b) c
af = arr f

I can't see how they can generalize functions of multiple arguments that return a single result

让输入类型为元组,输出为普通值。比如拿箭头

plus :: a (num, num) num
let plus = arr (\(a, b) -> a + b) -- arr (uncurry (+))

或者,您可以采用 "nested arrows" - 具有多个参数的柯里化函数不过是 returns 一个函数的函数。所以我们有一个箭头,其结果是另一个箭头:

plus :: a num (a num num)
let plus = arr (arr . (+))

要使用它,我们需要一个 ArrowApply 实例。首先,您将箭头与另一个箭头组合,从您的输入

创建第二个参数
plusWithIncrement :: a num (a num num, num)
let plusWithIncrement = plus &&& arr (+1)

然后你可以运行那

plusWithIncrement >>> app :: a num num

(这是一种过于复杂的写法arr (\x -> x + (x+1))