我正在为我在Scala中构建的实验库开发DSL,并且遇到了一些令人烦恼的Scala类型推理特性,因为它涉及到lambda表达式参数似乎没有在书Programming In Scala。复杂的Scala类型推理w/Lambda表达式
在我的库中,我有一个特征Effect [-T],用于表示可以应用于T类型对象的临时修饰符。我有一个对象myEffects,它有一个名为+ =接受类型为Effect [PlayerCharacter]的参数。最后,我有一个泛型方法,当[T]用于通过接受条件表达式和另一个效果作为参数来构造条件效果时。签名是如下:
def when[T](condition : T => Boolean) (effect : Effect[T]) : Effect[T]
当我所说的“时”的方法与上述签名,传递它的结果到+ =方法,它是无法推断的参数lambda表达式的类型。
myEffects += when(_.hpLow()) (applyModifierEffect) //<-- Compiler error
如果我将“when”的参数组合到单个参数列表中,Scala能够推断出lambda表达式的类型就好了。
def when[T](condition : T => Boolean, effect : Effect[T]) : Effect[T]
/* Snip */
myEffects += when(_.hpLow(), applyModifierEffect) //This works fine!
它也适用,如果我完全删除第二个参数。然而,出于美学的原因,我真的希望将参数作为单独的参数列表传递给“when”方法。
我从Programming in Scala的第16.10节中了解到,编译器首先查看方法类型是否已知,如果是,则使用它来推断它的参数的预期类型。在这种情况下,最外面的方法调用是+ =,它接受类型为Effect [PlayerCharacter]的参数。由于[T]为Effect [T]的返回类型以及要传递结果的方法需要Effect [PlayerCharacter]类型的参数,因此可以推断出T是PlayerCharacter,因此lambda的类型表达式作为第一个参数传递给“when”是PlayerCharacter => Boolean。这似乎是它在一个参数列表中提供参数时的工作方式,那么为什么将参数分成两个参数列表会将其分开呢?
http://pchiusano.blogspot.com/2011/05/making-most-of-scalas-extremely-limited.html – retronym