The next code
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
}
gives the error message
- type mismatch; found : List[List[Any]] required: List[List[Char]]
Please help me understand why 'for' chooses the most general Any instead of Char here? What topic in language spec should I read? Thanks.
The Scala compiler can infer the types of expressions automatically from contextual information. Therefore, we need not declare the types explicitly. This feature is commonly referred to as type inference. It helps reduce the verbosity of our code, making it more concise and readable.
Scala compiler can automatically infer types of each variable declared. If the value of a variable is declared in double-quotes it will automatically be inferred as String. Also, the compiler can infer any value in a single quote is inferred as Char. The compiler, by default it infer any number without decimal as Int.
Scala offers a lightweight notation for expressing sequence comprehensions. Comprehensions have the form for (enumerators) yield e , where enumerators refers to a semicolon-separated list of enumerators. An enumerator is either a generator which introduces new variables, or it is a filter.
yield keyword will returns a result after completing of loop iterations. The for loop used buffer internally to store iterated result and when finishing all iterations it yields the ultimate result from that buffer.
The result, you are yielding
is a mix of List[List[List[Char]]]
and List[List[Char]]
. Scala upcasts that to List[List[Any]]
. For your case either of the following will do the job:
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]]
The problem is List(x)
-- it needs to be x
.
First, v
iterates over the results of f(xs)
, and f
returns List[List[Char]]
. That means the result will be List[X]
, where X
is the type returned by yield
.
The type of v
is List[Char]
, since it is iterating over the contents of f(xs)
. So we have to figure out the type of List(x) :: v
, which is prepending a List[Char]
on a List[Char]
. It is not concatenating them: it is adding a list to a list containing only characters. The resulting list will have both Char
and List[Char]
in it.
Since the only type that satisfy both is Any
, then X
will be Any
and the result of the for-comprehension List[Any]
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With