多个参数闭包参数类型未推断

时间:2012-02-02 18:59:48

标签: scala compiler-construction types programming-languages type-inference

我有一段代码,我不能按照我喜欢的方式行事。我有一个按以下方式定义的类(为此被剥离):

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并传入函数并假设此处UInt。有没有办法解决这个问题而不指定输入参数的类型(对于闭包或泛型)?

编辑:我有两个修正案的例子:

beh.map1[Int, Int](beh2, (a, b) => a + b)
beh.map1(beh2, (a, b : Int) => a + b)

2 个答案:

答案 0 :(得分:19)

有关此处发生的事情的讨论,请参阅this scala-debate thread。问题是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

答案 1 :(得分: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将在第一个参数列表编译期间推断,第二个参数列表将使用已推断的类型。

相关问题