2016-03-24 14 views
1

Beim Versuch Scala implicits zu erfassen, lief ich in dieser Art Inferenzproblem:Scala Typinferenz implizit aufgelöst anonyme Funktionen

object Demo extends App { 

    def demo(f: (Int, Int) => Int) = ??? 

    demo((a: Int) => 42) 
    demo((a) => 42) // <-- any tricks to make this compile? 

    implicit def f1Tof2(f: Int => Int): (Int, Int) => Int = 
    (a: Int, b: Int) => f.apply(a) 

} 

Was ist der Grund für die Unfähigkeit der Compiler den Typ richtig zu schließen? Irgendwelche Tricks, damit es funktioniert?

+2

Stellen Sie sicher, dass auch relevante Nachrichten enthalten sind. – user2864740

+0

Guter Punkt! Der Kompilierfehler ist "fehlender Parametertyp". – netzwerg

+0

In meinem Fall sagt der Compiler: "falsche Anzahl von Parametern: erwartet 2'. Compiler weiß nicht, dass dieser Typ von' (a) '' Int' ist (weil es nicht spezifiziert ist), so kann es nicht implizit gelten. – dmitry

Antwort

3

Dies ist nicht möglich. Wenn Sie demo((a, b) => a + b) (zum Beispiel) aufrufen, erwartet der Compiler bereits (Int, Int) => Int, so wird es (a, b) => a + b als (Int, Int) => Int ableiten, da es die richtige Form hat.

Wenn Sie jedoch demo(a => 42) aufrufen, sieht der Compiler als Argument ein Function1[?, Int], ohne Angabe, was der Parametertyp ist. Da demo einen Function2 erwartet, ist die einzige Möglichkeit, die kompiliert werden kann, wenn der Compiler eine implizite Konvertierung von dem übergebenen Argumenttyp zu (Int, Int) => Int finden kann. Aber es kann nicht, weil es den Typ, den es konvertiert, von nicht kennt. Es kann nicht einfach davon ausgehen, dass es ein Int => Int wird.

Es gibt nur zwei Möglichkeiten, dies zu erreichen.

1.) Erklären Sie explizit den Parametertyp der anonymen Funktion, wie Sie es bereits getan haben. Nur so kann die implizite Konvertierung angewendet werden.

demo((a: Int) => 42) 

2.) eine Überlast für demo bereitzustellen, die eine Int => Int annimmt.

def demo(f: (Int, Int) => Int): Int = f(1, 2) 
def demo(f: Int => Int): Int = demo((a, b) => f(a)) 

scala> demo(a => 42) 
res3: Int = 42