无法推断多参数闭包参数类型

问题描述 投票:0回答:2

我有一段代码无法按照我想要的方式运行。我有一个按以下方式定义的类(为此进行了精简):

class Behaviour[T](private val rule: Time => T) {
  def map1[U, V](behaviour: Behaviour[U], func: (T, U) => V): Behaviour[V] = {
    new Behaviour(time => func(this.at(time), behaviour.at(time)))
  }
}

在玩这门课时,我尝试了一些我认为微不足道的事情:

val beh = Behaviour(time => 5)
val beh2 = Behaviour(time => 5)
beh.map1(beh2, (a, b) => a + b)

对于最后一行,我收到以下错误:

<console>:13: error: missing parameter type
          beh.map1(beh2, (a, b) => a + b)
                             ^

我当然可以指定闭包参数类型并且它可以正常工作,但是为什么类型推断在这里不起作用?当然,我也可以指定函数的泛型类型(两种解决方案见下文)。

我认为 Scala 执行了“扫描”来推断类型,并且会看到

beh2
并传递到函数中,并假设此处的
U
Int
。有什么方法可以解决这个问题而不指定输入参数的类型(对于闭包或泛型)?

编辑:我拥有的两个修复示例:

beh.map1[Int, Int](beh2, (a, b) => a + b)
beh.map1(beh2, (a, b : Int) => a + b)
scala types type-inference
2个回答
19
投票

请参阅

scala-debate
线程,了解此处发生的情况的讨论。问题是 Scala 的类型推断发生在每个参数列表,而不是每个参数

正如 Josh Suereth 在该帖子中指出的那样,当前的方法有一个很好的理由。如果 Scala 具有按参数类型推断,则编译器无法推断同一参数列表中类型的上限。考虑以下几点:

trait X
class Y extends X
class Z extends X

val y = new Y
val z = new Z

def f[A](a: A, b: A): (A, A) = (a, b)
def g[A](a: A)(b: A): (A, A) = (a, b)

f(y, z)
的工作方式完全符合我们的预期,但是
g(y)(z)
给出了类型不匹配,因为当编译器到达第二个参数列表时,它已经选择
Y
作为
A
的类型。


4
投票

解决此问题的方法之一是定义多个参数列表。所以你的

map1
方法将被定义如下:

def map1[U, V](behaviour: Behaviour[U])(func: (T, U) => V): Behaviour[V] = ...

你可以这样使用它:

beh.map1(beh2)((a, b) => a + b)
beh.map1(beh2)(_ + _)

我不完全确定为什么类型推断在您的情况下不起作用,但我相信它与

U
类型参数的使用有关。您使用它两次 - 对于第一个和第二个参数。对于编译器来说可能太复杂了,无法弄清楚。如果有 2 个参数列表,将在第一个参数列表编译期间推断
U
,第二个参数列表将使用已推断的类型。

© www.soinside.com 2019 - 2024. All rights reserved.