I am working on a piece of code that looks kind of like the following (Scastie for your convenience):
import scala.language.higherKinds
sealed trait Wrapping
sealed trait PinkWrap extends Wrapping
sealed trait GreenWrap extends Wrapping
sealed trait Foo[M[_], A] {}
case class MintFoo[M[_], A](a : A) extends Foo[M,A]
case class LiquoriceFoo[M[_], A](a : A) extends Foo[M,A]
sealed trait WrappedFoo[M[_], _, A]
case class FooInPinkWrap[M[_], A](m: Foo[M, A]) extends WrappedFoo[M, PinkWrap, A]
case class FooInGreenWrap[M[_], A](m: Foo[M, A]) extends WrappedFoo[M, GreenWrap, A]
object Utils {
def analyzeFoo[M[_], S <: Wrapping, A](w: WrappedFoo[M, S, A]): String = {
w match {
case FooInPinkWrap(f: Foo[M,A]) => tasteFoo[M,A](f)+" in Pink wrapping"
case FooInGreenWrap(f: Foo[M,A]) => tasteFoo[M,A](f)+" in Green wrapping"
}
}
def tasteFoo[M[_], A](f: Foo[M,A]) : String =
f match {
case MintFoo (a) => "Mint"
case LiquoriceFoo (a) => "Liquorice"
}
}
It used to compile perfectly fine with Scala 2.11.7.
Ever since the project has been bumped to Scala 2.12.4 (but in fact the issue is reproducible already with Scala 2.11.11) it fails to compile with the following message from scalac
for the line case FooInPinkWrap(f: Foo[M,A]) => tasteFoo[M,A]
:
M takes no type parameters, expected: one
This is reproducible right within Scastie by choosing Scala Version 2.12.4 under "Build Settings".
This is puzzling to me, since M
is indeed 1-ary.
In fact, I run into the very same issue with the following, simpler MWE (Scastie):
import scala.language.higherKinds
sealed trait GiftWrap
sealed trait PinkWrap extends GiftWrap
sealed trait GreenWrap extends GiftWrap
sealed trait Foo[M[_], A] {}
sealed trait WrappedFoo[M[_], S, A]
case class FooInPinkWrap[M[_], A](m: Foo[M, A]) extends WrappedFoo[M, PinkWrap, A]
case class FooInGreenWrap[M[_], A](m: Foo[M, A]) extends WrappedFoo[M, GreenWrap, A]
object Utils {
def tellColor[M[_], S <: GiftWrap, A](w: WrappedFoo[M, S, A]): String = {
w match {
case FooInPinkWrap(f: Foo[M,A]) => "Pink"
case FooInGreenWrap(f: Foo[M,A]) => "Green"
}
}
}
Replacing M
with ({type T[X] = M[X]})#T
in the latter piece of code results in
pattern type is incompatible with expected type; found : Playground.this.Foo[[X],A] required: Playground.this.Foo[Any,Any] Note: [X] <: Any, but trait Foo is invariant in type M. You may wish to define M as +M instead. (SLS 4.5) Note: A <: Any, but trait Foo is invariant in type A. You may wish to define A as +A instead. (SLS 4.5) M does not take type parameters
Notice found : Playground.this.Foo[[X],A]
.
Why does this happen?
I don't find the changelog for 2.11.11 (a minor release) particularly enlighting.
More importantly, how do I make the old code compile
- The right way
- The minimum-amount-of-modifications way?
Thanks.