给出
trait Foo {
type Bar
}
是否有合法的方法来编写类似f: (x: Foo) => x.Bar
的内容,以便函数的返回类型取决于参数?使用的一个例子是
def compareOutput(x1: Foo, x2: Foo)(f: (x: Foo) => x.Bar /* illegal */)(comparer: (x1.Bar, x2.Bar) => Boolean) = {
val y1 = f(x1)
val y2 = f(x2)
comparer(y1, y2)
}
答案 0 :(得分:8)
Scala没有像Haskell那样的多态函数。函数类型总是具体的。只有方法可以是多态的。不幸的是,这意味着您的假设类型(x: Foo) => x.Bar
在Scala中无法表达。
将通用方法转换为函数时,这一点很明显:所有类型信息都丢失了:
scala> def foo[Bar](x: Bar): Bar = ???
foo: [Bar](x: Bar)Bar
scala> foo _
res1: Nothing => Nothing = <function1>
您可能还注意到scala无法将具有依赖类型的方法转换为函数。那是因为不可能满足你的假设类型:
scala> def foo(x: Foo): x.Bar = ???
foo: (x: Foo)x.Bar
scala> foo _
<console>:10 error: method with dependent type (x: Foo)x.Bar cannot be converted
to function value.
然而,您的问题有几种解决方案。一种方法是将依赖类型的方法封装在辅助特征中:
trait FooFunc {
def apply(x: Foo): x.Bar
}
def compareOutput(x1: Foo, x2: Foo)(f: FooFunc)(comparer: ...) = {
val y1 = f(x1)
val y2 = f(x2)
comparer(y1,y2)
}
然后,您可以创建FooFunc的实例,您可以将其传递到compareOutput
方法。
答案 1 :(得分:1)
Scala 3预计将于今年(2020年)发布。它将具有(实际上已经具有)依赖的函数类型,在“ Dotty”文档中对此进行了描述:
https://dotty.epfl.ch/docs/reference/new-types/dependent-function-types.html