简体   繁体   English

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

[英]Multiple parameter closure argument type not inferred

I have a piece of code that I can't get to behave in the way I'd like. 我有一段代码,我不能按照我喜欢的方式行事。 I have a class defined in the following way (stripped down for this): 我有一个以下面的方式定义的类(为此被剥离):

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)))
  }
}

When playing around with this class I tried to something that I thought would be trivial: 在玩这堂课的时候,我尝试了一些我认为微不足道的东西:

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

For the last line I receive the following error: 对于最后一行,我收到以下错误:

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

I can of course specify the closure parameter types and it works correctly but why doesn't type inference work here? 我当然可以指定闭包参数类型,它可以正常工作,但为什么不在此处键入推理? Of course I could also specify the generic types for the function (see below for both solutions). 当然,我也可以为函数指定泛型类型(请参阅下面的两个解决方案)。

I thought Scala carried out a 'scan' to infer types and would see beh2 and passed into the function and assume U here to be Int . 我认为Scala进行了一次'扫描'来推断类型并且会看到beh2并传递给函数并假设U在这里是Int Is there some way I can fix this without specify the types of the input parameters (for the closure or the generics)? 有没有什么方法可以解决这个问题,而无需指定输入参数的类型(对于闭包或泛型)?

EDIT: Examples of the two fixes I have: 编辑:我有两个修复示例:

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

See this scala-debate thread for a discussion of what's going on here. 请参阅scala-debate主题 ,讨论此处发生的事情。 The problem is that Scala's type inference happens per parameter list , not per parameter . 问题是Scala的类型推断发生在每个参数列表中 ,而不是每个参数

As Josh Suereth notes in that thread, there's a good reason for the current approach. 正如Josh Suereth在那篇文章中指出的那样,目前的方法是有充分理由的。 If Scala had per-parameter type inference, the compiler couldn't infer an upper bound across types in the same parameter list. 如果Scala具有每参数类型推断,则编译器无法推断同一参数列表中的类型的上限。 Consider the following: 考虑以下:

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) works exactly as we'd expect, but g(y)(z) gives a type mismatch, since by the time the compiler gets to the second argument list it's already chosen Y as the type for A . f(y, z)完全按照我们的预期工作,但g(y)(z)给出了类型不匹配,因为当编译器到达第二个参数列表时,它已经选择Y作为A的类型。

One of the ways to fix this is to define multiple argument lists. 解决此问题的方法之一是定义多个参数列表。 So your map1 method would be defined like this: 所以你的map1方法定义如下:

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

and you can use it like this: 你可以像这样使用它:

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

I'm not completely sure why type inference does not work in your case, but I believe that it has something to do with usage of U type parameter. 我不完全确定为什么类型推断在你的情况下不起作用,但我相信它与U类型参数的使用有关。 You are using it twice - for the first and second argument. 您正在使用它两次 - 第一个和第二个参数。 It's probably too complicated for compiler to figure it out. 编译器弄清楚它可能太复杂了。 In case of 2 argument lists, U would be inferred during first argument list compilation, and the second argument list will use already inferred type. 在2个参数列表的情况下, U将在第一个参数列表编译期间推断,第二个参数列表将使用已推断的类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM