2012-11-21 14 views
5

Stavo cercando di invertire una lista di interi come segue:inferenza di tipo nella piega sinistra?

List(1,2,3,4).foldLeft(List[Int]()){(a,b) => b::a} 

La mia domanda è che c'è un modo per specificare il seme di essere un po 'List[_] dove il _ è il tipo completati automaticamente da del tipo di scala meccanismo di inferenza, invece di dover specificare il tipo come List[Int]?

Grazie

+0

C'è qualche motivo pratico per questo? Qual è il contesto? Perché 'List [_]' ha solo 2 caratteri più brevi di 'List [Int]'. E per invertire una lista, dovresti comunque usare '.reverse'. – rolve

+1

Nessun motivo pratico, solo un prurito strano per conoscere i limiti del sistema di inferenza del tipo di scala –

+0

Ok. Sulla base di questo, ho pubblicato una risposta teorica e non un work-around. – rolve

risposta

5

Aggiornamento: Dopo aver letto un po 'di più sulla inferenza di tipo di Scala, ho trovato una risposta migliore alla tua domanda. This article che è circa le limitazioni del inferenza di tipo Scala dice:

informazioni Tipo a Scala scorre da argomenti delle funzioni ai loro risultati [...], da sinistra a destra attraverso liste di argomenti, e dalla prima alla ultimo tra le dichiarazioni. Questo è in contrasto con una lingua con inferenza di tipo completo, in cui (approssimativamente) il tipo di informazioni scorre senza restrizioni in tutte le direzioni.

Quindi il problema è che l'inferenza di tipo di Scala è piuttosto limitata. È prima esamina il primo elenco di argomenti (l'elenco nel tuo caso) e quindi nella seconda lista di argomenti (la funzione). Ma non torna indietro.

Questo è il motivo né questo

List(1,2,3,4).foldLeft(Nil){(a,b) => b::a} 

né questo

List(1,2,3,4).foldLeft(List()){(a,b) => b::a} 

funzionerà. Perché? In primo luogo, la firma di foldLeft è definito come:

foldLeft[B](z: B)(f: (B, A) => B): B 

Quindi, se si utilizza Nil come primo argomento z, il compilatore assegna Nil.type al parametro di tipo B. E se si utilizza List(), il compilatore utilizzerà List[Nothing] per B.

Ora, il tipo del secondo argomento f è completamente definito. Nel tuo caso, è sia

(Nil.type, Int) => Nil.type 

o

(List[Nothing], Int) => List[Nothing] 

E in entrambi i casi l'espressione lambda (a, b) => b :: a non è valido, dal momento che il suo tipo di ritorno è dedotto di essere List[Int].


Si noti che la parte in grassetto sopra dice "liste di argomenti" e non "argomenti".L'articolo spiega poi:

informazioni Tipo non scorre da sinistra a destra all'interno una lista di argomenti, solo da sinistra a destra in tutta liste di argomenti.

Quindi la situazione è anche peggiore se si dispone di un metodo con un elenco di argomenti singoli.

+0

Incredibile - Ha molto più senso ora. Grazie –

4

L'unico modo che conosco è

scala> def foldList[T](l: List[T]) = l.foldLeft(List[T]()){(a,b) => b::a} 
foldList: [T](l: List[T])List[T] 

scala> foldList(List(1,2,3,4)) 
res19: List[Int] = List(4, 3, 2, 1) 

scala> foldList(List("a","b","c")) 
res20: List[java.lang.String] = List(c, b, a)