2015-02-11 12 views
7

Ho un problema di conversioni implicite e funzioni di ordine superiore. Sembra che una conversione implicita di una funzione in una funzione di secondo ordine funzioni solo se la funzione da convertire ha almeno due parametri.La conversione implicita di una funzione in una funzione di secondo ordine funziona solo se la funzione da convertire ha almeno due parametri

Works:

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

non funziona:

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

Works:

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

esempio completo con punto di guasto:

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

Cosa mi manca?

Grazie!

+2

si presenta come un verruca risoluzione implicita a Scala a me. Quale versione di Scala è questa? – gzm0

risposta

-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 

E 'la conversione tra A => B e Function1[A,B] che non sta accadendo.

Inoltre v'è un tipo Function in Predef - notare le differenze di tipo qui:

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 

E 'un alias a Function1, ma con diversi limiti di tipo (come sottolineato nei commenti qui sotto).

+0

Oppure puoi anche assegnare 'baadf00d' a un val usando' val baadf00d2 = baadf00d _' e poi funziona –

+0

: type e: kind li trattano in modo uniforme nel REPL, facendolo apparire ancora più strano. –

+2

da Predef.scala "tipo Funzione [-A, + B] = Funzione1 [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! 
    // ¯\_(ツ)_/¯ 

Il problema è come le conversioni implicite lavorano su Scala e il fatto che ci sono al curry e le funzioni uncurried a Scala.

Questo è qualcosa che DOVREBBE funzionare ma non lo è ed è probabilmente solo un altro bug del compilatore (preparatevi ad incontrarne molti altri mentre usate Scala sempre di più).

EDIT: Per quanto riguarda il tuo ultimo esempio

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 

Questo perché ci le definizioni di funzione corrispondono. La conv si aspetta una funzione (Int, Int) => String e una normale definizione di metodo (non criptata) in scala, come la definizione di baadf00d, si trasforma in quella.

Ad esempio, una funzione:

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

ottiene trasformato in un

(Int, Int) => String 

Si noti che i 2 Ints sono tupled! Questa non è la stessa di:

Int => Int => String 

Se si dovesse ridefinire baadf00d in:

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

Che il codice non viene compilato, perché baadf00d è ora "diverso", anche se si sta facendo la stessa cosa.

Per ulteriori informazioni, guarda la definizione degli oggetti:

Function1, Function2, Function3 .... 

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

+0

Ok, quindi il motivo per cui la seconda conversione non funziona è solo a causa di un errore del compilatore, suppongo che ... – user3612643

+0

Sì. In Scala, 'baadf00d' e' goodf00d' dovrebbero essere trasformati in '(Int) => String' e' Int => String' rispettabilmente. Ora queste cose DOVREBBE essere lo stesso, ma per qualche ragione, la Risoluzione implicita pensa che siano differenti. Il fatto che tu possa passare 'baadf00d' in' conv' prova che sono gli stessi, solo la risoluzione implicita è troppo stupida per capirlo. – Nacht