【问题标题】:Are Arrows a true generalization of functions?箭头是功能的真正概括吗?
【发布时间】:2015-04-14 00:08:57
【问题描述】:

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

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

【问题讨论】:

  • 你看过ArrowApply吗?
  • ArrowApply 确实解决了多个参数的问题,但是它也带来了部分应用/闭包的额外功能......
  • 说实话,我不确定我是否理解这个问题。由于函数实际上是箭头(有一个instance Arrow (->)),很明显箭头泛化了函数。那么“真正的概括”是什么意思呢?箭头必须是什么情况才能成为“真正的”函数泛化?
  • 我承认这个问题可能没有意义,并且可能反映了我的误解。我看不到 Arrow 接口如何支持多个参数的箭头组合,但正如下面的答案所指出的,这不是问题,只需构造一个箭头 Arrow (a,b) c 并组合即可。我认为这在某种意义上是作弊,因为它依赖于将某种函数(需要一个元组的函数)提升到箭头中,但我想这不是一个真正的问题。
  • @Daniel Wagner 我的意思是“真正的泛化”,非正式意义上的“泛化是否捕获了我们想要的一切?”。我知道 Haskell 将函数类型定义为 Arrow 类型类的实例。然而,无论出于何种原因,我都没有想到明确定义一个输入类型为元组的箭头是完全合理的,就像用元组作为参数声明函数(即非柯里化多参数函数)是有效的一样。你认为我应该改写这个问题吗?

标签: haskell arrows


【解决方案1】:

我看不出他们如何概括返回单个结果的多个参数的函数

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

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)) 的写法过于复杂)

【讨论】:

  • 出于某种原因,我一直在想,构造一个带有显式元组类型的箭头作为输入在某种程度上是作弊,但我意识到这一切照旧。正如您所指出的,柯里化方法需要 ArrowApply,这显着增加了 Arrow 类型的功能:它们现在可以像 lambda 演算中的函数一样动态构建。
【解决方案2】:

你可以用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

【讨论】:

  • 嵌套箭头方法需要 ArrowApply 但正如您指出的那样,我真正需要的是一个接受元组的箭头。我接受了 Bergi 的回答,只是因为它更明确地说明了需要应用函数来评估的嵌套箭头。
猜你喜欢
  • 2015-01-05
  • 2019-02-01
  • 2019-06-25
  • 1970-01-01
  • 2017-12-27
  • 2016-11-29
  • 1970-01-01
  • 2019-02-09
  • 1970-01-01
相关资源
最近更新 更多