2013-05-10 4 views
5

Следующий код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 
    } 

дает сообщение об ошибке

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

Пожалуйста, помогите мне понять, почему «за» выбирает наиболее общий Любой вместо Char здесь? Какую тему в спецификации языка я должен прочитать? Благодарю.

ответ

10

Результат: yielding - это смесь List[List[List[Char]]] и List[List[Char]]. Scala повышает до List[List[Any]]. В вашем случае одно из следующих действий будет делать работу:

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

Проблема заключается в том List(x) - она ​​должна быть x.

Во-первых, v выполняет итерацию по результатам f(xs) и f возвращает List[List[Char]]. Это означает, что результат будет List[X], где X - это тип, возвращаемый yield.

Тип v: List[Char], так как он итерирует содержимое f(xs). Поэтому нам нужно выяснить тип List(x) :: v, который добавляет List[Char] на List[Char]. Это не, объединяющий их: он добавляет список в список, содержащий только символы. Полученный список будет содержать как Char, так и List[Char].

Поскольку единственный тип, который удовлетворяет как это Any, то X будет Any и результат для-пониманий List[Any].

Смежные вопросы