According to section 6.19 of the Scala Language Specification this for loop:
for (e <-p) e'
is translated to:
p <- e.withFilter{case p => true; case _ => false}.foreach{case p => e′}
So, why this small program:
object ForAndPatterns extends App {
class A()
class B() extends A
val list: List[A] = List(new A(), new B(), new B())
for {b: B <- list}
println(b)
}
gives this compilation error:
Error:(7, 13) type mismatch;
found : proves.ForAndPatterns.B => Unit
required: proves.ForAndPatterns.A => ?
for {b: B <- list}
when this expression:
list.withFilter{case a: B => true; case _ => false}.foreach{case b => println(b)}
gives no error.
The translation you get from specification is actually
list.withFilter{case b: B => true; case _ => false}.foreach{case b: B => println(b)}
but it still compiles and works. It seems like Scala is losing the case
and translating to
list.withFilter{case b: B => true; case _ => false}.foreach{b: B => println(b)}
which would give the same error.
This turns out to be a known and old bug: https://github.com/scala/bug/issues/900.
Workaround provided there:
object Typed { def unapply[A](a: A) = Some(a) }
for { Typed(b: B) <- list } println(b)
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