sealed abstract class Animal
case class Dog(name: String) extends Animal
case class Cat(age: Int) extends Animal
def foo[A <: Animal](a: A): A = a match {
case d: Dog => d
case c: Cat => c
}
val dog: Dog = foo(new Dog("boxer"))
val cat: Cat = foo(new Cat(1))
When i do foo(new Dog("boxer")) we would have let the compiler know that A is Dog and case d: Dog => d returns a Dog which type checks but the compiler complains
Error:(76, 20) type mismatch;
found : d.type (with underlying type sandbox.Main.Dog)
required: A
case d: Dog => d
sealed abstract class Animal
case class Dog(name: String) extends Animal
case class Cat(age: Int) extends Animal
def foo(a: Animal): Animal = a match {
case d: Dog => d
case c: Cat => c
}
val dog: Animal = foo(new Dog("boxer"))
val cat: Animal = foo(new Cat(1))
The compiler isn’t smart enough to know that the body of the function always returns the same type as what is fed in in this situation.
In this situation, you can workaround by returning a. In the less trivial cases where you can’t, it’s plausible that it’s not safe for all cases.
I find it strange that the compiler isn’t smart enough to figure that out, but is smart enough for this:
sealed trait A[T]
case class B() extends A[Int]
case class C() extends A[String]
def foo[T](a: A[T]): T = a match {
case b: B => 42
case c: C => "foo"
}