2015-02-11 7 views
7

Ich habe ein Problem mit impliziten Konvertierungen und Funktionen höherer Ordnung. Es scheint, dass eine implizite Umwandlung einer Funktion in eine Funktion zweiter Ordnung nur funktioniert, wenn die zu konvertierende Funktion mindestens zwei Parameter hat.Die implizite Umwandlung einer Funktion in eine Funktion zweiter Ordnung funktioniert nur, wenn die Konvertierungsfunktion mindestens zwei Parameter hat.

Works:

implicit def conv(foo: Integer => String): String => String = null 

funktioniert nicht:

implicit def conv(foo: Integer => String): String => String => String = null 

Works:

implicit def conv(foo: (Integer, Integer) => String): String => String => String = null 

Voll Beispiel mit Point of Failure:

{ 
    implicit def conv(foo: Integer => String): String => String = null 

    def baadf00d(foo: Integer): String = null 

    def deadbeef(foo: String => String) = null 

    deadbeef(conv(baadf00d)) 

    deadbeef(baadf00d) 
} 

{ 
    implicit def conv(foo: Integer => String): String => String => String = null 

    def baadf00d(foo: Integer): String = null 

    def deadbeef(foo: String => String => String) = null 

    deadbeef(conv(baadf00d)) 

    deadbeef(baadf00d) // <-------- DOES NOT COMPILE! 
} 

{ 
    implicit def conv(foo: (Integer, Integer) => String): String => String => String = null 

    def baadf00d(foo: Integer, bar: Integer): String = null 

    def deadbeef(foo: String => String => String) = null 

    deadbeef(conv(baadf00d)) 

    deadbeef(baadf00d) 
} 

Was fehlt mir?

Danke!

+2

Sieht aus wie eine implizite Auflösung Warze in Scala zu mir. Welche Scala-Version ist das? – gzm0

Antwort

-1
implicit def conv1(a: Function1[Int, String]): Function2[String, String, String] = null 
def baadf00d1(i: Int): String = null 
def deadbeef1(arg: Function2[String, String, String]) = null 
deadbeef(baadf00d) // compiles 

Es ist die Umwandlung zwischen A => B und Function1[A,B] das nicht geschieht.

Auch gibt es eine Function Art in Predef - hier die Art Unterschiede feststellen:

scala> val f1: Function[Int, Int] = null 
f1: Function[Int,Int] = null 

scala> val f2: Function1[Int, Int] = null 
f2: Int => Int = null 

scala> :type f1 
Function[Int,Int] 

scala> :type f2 
Int => Int 

Es ist ein Alias ​​für Function1, aber mit unterschiedlicher Art Grenzen (wie unten in den Kommentaren darauf hingewiesen).

+0

Oder Sie können sogar 'baadf00d' mit' val baadf00d2 = baadf00d _' einem val zuweisen und dann funktioniert es –

+0

: Typ und: Art behandeln sie gleichmäßig in der REPL, so dass es noch seltsamer erscheinen. –

+2

von Predef.scala "Typ Funktion [-A, + B] = Funktion1 [A, B]" – zarthross

3
implicit def conv(foo: Integer => String): String => String => String = ??? 

    def baadf00d(i: Integer): String = ??? 
    def goodf00d: Integer => String = _ => ??? 

    def deadbeef(foo: String => String => String) = ??? 

    deadbeef(conv(baadf00d)) 

    deadbeef(baadf00d) // <-------- DOES NOT COMPILE! 
    deadbeef(goodf00d) // <-------- COMPILE! 
    // ¯\_(ツ)_/¯ 

Die Frage ist, wie implizite Konvertierungen auf Scala und der Tatsache arbeiten, dass es curried und uncurried Funktionen in Scala sind.

Dies ist etwas, das funktionieren sollte, aber nicht und ist wahrscheinlich nur ein weiterer Compiler-Bug (machen Sie sich bereit, viele mehr zu treffen, wie Sie mehr und mehr Scala verwenden).

EDIT: Was Ihr letztes Beispiel

implicit def conv(foo: (Integer, Integer) => String): String => String => String = null 

def baadf00d(foo: Integer, bar: Integer): String = null 

def deadbeef(foo: String => String => String) = null 

Das ist, weil es die Funktionsdefinitionen übereinstimmen. Die Konv erwartet eine Funktion (Int, Int) => String und eine normale Methodendefinition (uncurried) in scala, wie baadf00d definiert ist, wird in das.

Zum Beispiel eine Funktion:

def f(a: Int, b: Int): String 

Ruft verwandelte sich in eine

(Int, Int) => String 

Beachten Sie, dass die 2 Ints fach vervielfachten werden! Dies ist nicht das gleiche wie:

Int => Int => String 

Wenn Sie baadf00d in neu zu definieren sind:

def baadf00d: Integer => Integer => String = _ => _ => ??? 

Dieser Code wird nicht kompiliert, da baadf00d ist nun „anders“, auch wenn es das tut, gleiche Sache.

Weitere Informationen Blick auf die Definition der Objekte:

Function1, Function2, Function3 .... 

http://www.scala-lang.org/api/current/#scala.Function2

+0

Okay, der Grund, warum die zweite Konvertierung nicht funktioniert, ist nur wegen eines Compiler-Bugs, denke ich ... – user3612643

+0

Ja. In Scala sollten 'baadf00d' und' goodf00d' respektabel in '(Int) => String' und' Int => String' umgewandelt werden. Nun sollten diese Dinge die gleichen sein, aber aus irgendeinem Grund denkt implizite Auflösung, dass sie anders sind. Die Tatsache, dass Sie "baadf00d" in "conv" überführen können, beweist, dass sie gleich sind, dass die implizite Auflösung zu dumm ist, um es herauszufinden. – Nacht