Вопрос

Suppose I have this monadic class:

case class Foo[A](xs: List[A]) {
  def map[B](f: A => B) = Foo(xs map f)
  def flatMap[B](f: A => Foo[B]) = Foo(xs flatMap f.andThen(_.xs))
  def withFilter(p: A => Boolean) = {
    println("Filtering!")
    Foo(xs filter p)
  }
}

The following is from a 2.10.0 REPL session:

scala> for { (a, b) <- Foo(List(1 -> "x")) } yield a
res0: Foo[Int] = Foo(List(1))

And here's the same thing in 2.10.1:

scala> for { (a, b) <- Foo(List(1 -> "x")) } yield a
Filtering!
res0: Foo[Int] = Foo(List(1))

This is completely unexpected (to me), and leads to particularly confusing errors in cases where filtering requires additional constraints (such as Scalaz's \/ or EitherT).

I wasn't able to find any discussion of this change in the 2.10.1 release notes. Can someone point out where and why this new desugaring behavior was introduced?

Это было полезно?

Решение

The story is more complex than that, and it's in fact a 2.10.0 regression that was plugged there.

The "no-withFilter" behavior was introduced in c82ecab, and because of things like SI-6968, this was reverted partially #1893. Further adaptations followed (SI-6646, SI-7183)

The takeaway sentence you're looking for is :

The parser can't assume that a pattern (a, b) will match, as results of .isInstanceOf[Tuple2] can't be statically known until after the typer.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top