Scala 泛型函数参考

scala generic function reference

我有几个具有相同签名的通用函数:

def f1[A, B](v: A, f: (A, B) => B): B = ...

def f2[A, B](v: A, f: (A, B) => B): B = ...

我需要定义一个函数 g 可以接受任何这些函数 (f1 f2):

def g(f: ????) = ...

g 内部使用了多种参数类型,所以我不能像那样参数化它:

def g[A, B](f: (A, (A, B) => B) => B) = ...

经过一番摸索,得出以下结论:

g(new FunctionHolder {
    def apply[A, B](): (A, (A, B) => B) => B = f1
})


def g(f: FunctionHolder) = f()(..., (a, b) => ...)

abstract class FunctionHolder {
    def apply[A, B](): (A, (A, B) => B) => B
}

但这看起来不对。

希望有更简洁的方法来做到这一点

在 Scala 2 中确实没有更好的方法。虽然你的解决方案有点奇怪,因为 FunctionHolderapply 方法将 return 一个函数object 并且本身不接受任何参数——这比它需要的要复杂一点。所以你可以这样做:

trait FunctionHolder {
  def apply[A, B](v: A, f: (A, B) => B): B
}

def g(f: FunctionHolder) = …

但这并没有那么好。

在 Scala 3 中,polymorphic function types 可以更简洁地执行此操作:

def g(f: [A, B] => (A, (A, B) => B) => B) = …

也就是说,我不相信那个类型签名真的是你想要的。请记住,当您定义带有类型参数的函数时,它需要为用户可能提供的 所有 可能的类型参数工作。无法为此签名完成…

def f1[A, B](v: A, f: (A, B) => B): B

... 因为当我有这样的函数时,我可以很容易地写出 Nothing:

类型的表达式
f1[Unit, Nothing]((), (a: Unit, b: Nothing) => b)

并且不可能编写 Nothing 类型的表达式,除非你作弊(例如抛出异常或进入无限循环或类似的东西)。所以类型签名告诉我你在作弊

如果你想了解更多关于这种推理的信息,请搜索“免费定理!”