2013-05-10 20 views
5

Il codice successivoScala per-comprensione inferenza di tipo

def f(chars: List[Char]): List[List[Char]] = chars match { 
    case Nil => List(Nil) 
    case x :: xs => for { 
     v <- f(xs) 
    } yield List(x) :: v 
    } 

dà il messaggio di errore

- type mismatch; found : List[List[Any]] required: List[List[Char]] 

Ti prego, aiutami a capire perché 'per' sceglie la più generale Qualsiasi invece di Char qui? Quale argomento nelle specifiche del linguaggio dovrei leggere? Grazie.

risposta

10

Il risultato, si è yielding è un mix di List[List[List[Char]]] e List[List[Char]]. Scala lo ha aggiornato a List[List[Any]]. Per il vostro caso una delle seguenti farà il lavoro:

scala> def f(chars: List[Char]): List[List[Char]] = chars match { 
    |  case Nil => List(Nil) 
    |  case x :: xs => for { 
    |  v <- f(xs) 
    |  } yield x :: v 
    | } 
f: (chars: List[Char])List[List[Char]] 

scala> def f(chars: List[Char]): List[List[Char]] = chars match { 
    |  case Nil => List(Nil) 
    |  case x :: xs => for { 
    |  v <- f(xs) 
    |  } yield List(x) ++ v 
    | } 
f: (chars: List[Char])List[List[Char]] 
6

Il problema è List(x) - ha bisogno di essere x.

Primo, v itera sui risultati di f(xs) e f restituisce List[List[Char]]. Ciò significa che il risultato sarà List[X], dove X è il tipo restituito da yield.

Il tipo di v è List[Char], poiché è scorrere il contenuto di f(xs). Quindi dobbiamo capire il tipo di List(x) :: v, che è prepending uno List[Char] su un List[Char]. È non concatenandoli: aggiunge un elenco a un elenco contenente solo caratteri. L'elenco risultante avrà sia Char e List[Char] in esso.

Poiché l'unico tipo che soddisfano entrambi è Any, allora X sarà Any e il risultato del per-comprensione List[Any].