箭头通常被描述为函数的泛化(仅限静态生成的函数,即不支持部分应用程序/闭包)。然而,至少看看在 Haskell 中建模的 Arrows,我看不出它们如何概括返回单个结果(通常可能不是元组的结果)的多个参数的函数。我试图想象如何仅使用箭头接口就可以得到一组箭头,该组合产生一个通常可能不是元组的单一结果。有没有办法做到这一点,或者这是对箭头类型的力量的故意限制?
据我了解,箭头提供了组成静态(可能是并行)管道的能力,但它们无法将输出元组“折叠”为单个最终结果。是我错了还是漏掉了什么?
我看不出他们如何概括返回单个结果的多个参数的函数
只需让输入类型为元组,输出为普通值即可。例如,取箭头
plus :: a (num, num) num
let plus = arr (\(a, b) -> a + b) -- arr (uncurry (+))
或者,您可以采用“嵌套箭头”——具有多个参数的柯里化函数只不过是一个返回函数的函数。所以我们会有一个箭头,其结果是另一个箭头:
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))
)
你可以用类型来思考函数
f :: a -> b -> c
作为一个函数,它接受
a
类型的值并生成另一个 b -> c
类型的函数。换句话说,
f :: a -> (b -> c)
箭头的概括非常简单:
f :: Arrow a (Arrow b c)
为了使用多个变量进行函数组合,您必须使用
(.)
运算符或 (<<<)
来表示箭头,进行一些疯狂的语义操作。 使具有多个参数的函数变得无指向麻烦同样的原因阻碍了语法以这种方式表达箭头,这就是为什么有如此多的组合器用于使用元组。此外,没有什么可以阻止您定义将元组映射到值的箭头。 arr
函数将任意函数变成箭头!
f :: (a, b) -> c
af :: Arrow (a, b) c
af = arr f