I'm probably missing something obvious, but I can't make this work.
Suppose we have the following code:
object T {
def method: Unit = {
trait Mixin
case class Foo(foo: String)
val f = new Foo("hi") with Mixin
f match {
case Foo(s) => println(s)
}
}
}
This compiles and prints "hi" when I call Test.method. The pattern match code can even be inside nested methods or nested functions, and it works. However, if I move the case class outside of method and directly attached to T2:
object T2 {
case class Foo(foo: String)
def method: Unit = {
trait Mixin
val f = new Foo("hi") with Mixin
f match {
case Foo(s) => println(s)
}
}
}
it throws the following error:
Error:(183, 12) constructor cannot be instantiated to expected type;
found : T2.Foo
required: T2.Foo with Mixin
case Foo(s) => println(s)
^
If now I don't use Mixin, and only make val f = new Foo("hi"), it works fine again. It also works if I try to match on its type:
val f = new Foo("hi") with Mixin
f match {
case f: Foo => println("I am a Foo")
}
Why doesn't T2 work, if the case class (and all of its generated methods) are in scope, and why would it matter where it is defined? In my real code, I have several case classes, in several modules, and the pattern matchers are all over the place, so I can't just move everything inside the same method, and I'd prefer if I don't have to get rid of the mixins, so what other alternative do I have?
I believe there are a few things going on.
In T
, both Foo
and Mixin
are declared locally in the scope of your method. A local type isn't necessary available outside of its scope (in this case, method
). Because everything is in the same scope, it's easy for the compiler to figure out what you're trying to do.
In T2
, Foo
is declared at the top level but Mixin
is still a local type. This seems to throw off the compiler. You can help the compiler by specifically typeing value f
to Foo
, which will allow your snippet to compile.
object T2 {
case class Foo(foo: String)
def method: Unit = {
trait Mixin
val f: Foo = new Foo("hi") with Mixin
f match {
case Foo(s) => println(s)
}
}
}
I wish I could give a more detailed (and guaranteed accurate) explanation.