创建部分应用的函数时键入推断

时间:2014-06-20 19:28:01

标签: scala type-inference

当我这样做时:

def x(i: Int, i2: Int, i3: Int) = i

x(_: Int, _: Int, 3)

为什么我必须指定前两个参数是“Int”?

有没有办法让编译器推断类型,以便我可以输入:

  x(_, _, 3)

1 个答案:

答案 0 :(得分:1)

简答:

除非需要函数类型,否则您必须明确指出匿名函数的参数类型。 “部分应用程序”只是用于创建匿名函数的语法糖。

答案很长:

首先,请注意,部分应用x时,总是不得提供类型参数。考虑这个例子:

def x(i: Int, i1: Int, i2: Int) = i

def g(f: (Int, Int) => Int) = f(1, 2)

// types are inferred!
g(x(_, _, 3)) // evaluates to 1

// again, types are inferred
val f: (Int, Int) => Int = x(_, _, 3)

很明显,在预期(Int, Int) => Int的情况下,它会有所帮助。

其次,请注意您正在定义匿名函数。您可以更明确地编写它:

(a, b) => x(a, b, 3) 

以这种方式编写,应该更清楚的是,定义上下文(即,作为单独的表达式)不会对匿名函数的类型产生任何期望。另一方面,在g的应用中,g的参数类型意味着对特定函数类型的期望。

原则上,编译器可以从a的类型推断出bx的类型,但它没有,如{{3的§6.23中所指定的那样(粗体强调添加):

  

匿名函数( x 1 T 1 ,..., x < sub> n T n )=&gt; e T i 类型的参数 x i 映射到表达式给出的结果ë。 [...]

     

如果预期的匿名函数类型的格式为scala.FunctionN [ S 1 ,..., S n R ], e 的预期类型是 R ,类型 T i <任何参数 x i 的/ sub> 都可以省略,在这种情况下 T i = S i 如果匿名函数的预期类型是其他类型,则必须明确指定所有形式参数类型,并且 e 的预期类型未定义。