I am using scala 2.11. I have question on the scala generic types and pattern matching.
In the class MyImpl.example(), compiler is unhappy saying type mismatch, Required: _$1, Found: X[_ <: A]
trait A
class B extends A
class C extends A
trait Foo[T <: A] {
def foo(arg: T): Unit
}
class Bar extends Foo[B] {
override def foo(arg: B): Unit = print("Bar")
}
class Car extends Foo[C] {
override def foo(arg: C): Unit = print("Car")
}
class MyImpl {
def getA(): A = {
new B()
}
def example(): Unit = {
getFoo("1").foo(getA())
}
def getFoo(something: String): Foo[_ <: A] = {
//return either
something match {
case "1" => new Bar()
case "2" => new Car()
}
}
}
object Test {
def main(args: Array[String]) = {
new MyImpl().example()
}
}
Note: getFoo("1") is more dynaminc in my real case, here is just an example.
I kind of understand this, compiler is unable to predict on which pair of the 2 implementation the method is invoked.
I am able to work around this, if I change the implementation of MyImpl.example() to
def example(): Unit = {
(getFoo("1"), getA()) match {
case (i: Bar, j: B) => i.foo(j)
case (i: Car, j: C) => i.foo(j)
}
}
I am not really happy with this as I am just repeating i.foo(j)
Any scala functional style writing much cleaner code?
Basically you want something like
or
You can remove code duplication in
(or fix compilation of
getFoo("1").foo(getA()))with nested pattern matching
if you add type member
_TFor
getFoo("1")andgetAproducingnew Bthis printsBar, vice versa forgetFoo("2")andnew Cthis printsCar, for other combinations this throwsClassCastExceptionsimilarly to (*).Please notice that this can't be rewritten as just a variable declaration and single pattern matching
because for nested pattern matching the types are inferred correctly (
i: Foo[t],j: t) but forval ithe type is existential (i: Foo[_]akai: Foo[_$1]after skolemization,j: _$1).