箭头通常被描述为函数的泛化(仅静态生成函数,即不支持部分应用/闭包)。但是,至少在Haskell中建模时看看Arrows,我看不出它们如何能够推广返回单个结果的多个参数的函数(通常可能不是元组的结果)。我试图设想如何仅使用箭头界面,可以得到一个箭头组合,产生一个通常可能不是元组的结果。有没有办法做到这一点,或者这是对箭头类型的力量的故意限制?
根据我的理解,箭头提供了组成静态(可能是并行)管道的能力,但是它们不能将输出的元组“折叠”成单个最终结果。我错了还是错过了什么?
箭头通常被描述为函数的泛化(仅静态生成函数,即不支持部分应用/闭包)。但是,至少在Haskell中建模时看看Arrows,我看不出它们如何能够推广返回单个结果的多个参数的函数(通常可能不是元组的结果)。我试图设想如何仅使用箭头界面,可以得到一个箭头组合,产生一个通常可能不是元组的结果。有没有办法做到这一点,或者这是对箭头类型的力量的故意限制?
根据我的理解,箭头提供了组成静态(可能是并行)管道的能力,但是它们不能将输出的元组“折叠”成单个最终结果。我错了还是错过了什么?
我看不出它们如何能够推广返回单个结果的多个参数的函数
只需输入类型为元组,输出为普通值。例如,拿箭头
plus :: a (num, num) num
let plus = arr (\(a, b) -> a + b) -- arr (uncurry (+))
或者,您可以使用“嵌套箭头” - 具有多个参数的curried函数只是一个返回函数的函数。所以我们有一个箭头,其结果是另一个箭头:
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