Given the below example, how can I make the code compile without resorting to casting in myMethod
?
object Test {
sealed trait MyTrait
case class A(v: Int) extends MyTrait
case class B(v: Int) extends MyTrait
def myMethod[T <: MyTrait](in0: T): T = {
in0 match {
case in: A => in.copy(v = 1)
case in: B => in.copy(v = 2)
}
}
}
Thanks.
You can try to:
identity
in
valueFor instance you could implement it like this
import scala.annotation.nowarn
sealed trait MyTrait
case class A(v: Int) extends MyTrait
case class B(v: Int) extends MyTrait
@nowarn
def myMethod[T <: MyTrait](in0: T): T = {
case class IntoT[A, B](value: A, upcast: A => B)
IntoT(in0, identity[T]) match {
case IntoT(in : A, upcastA: (A => T)) => upcastA(in.copy(v = 1))
case IntoT(in : B, upcastB: (B => T)) => upcastB(in.copy(v = 2))
}
}
It will make mismatching types error go away. Instead you will get warning that
match may not be exhaustive.
It would fail on pattern case: IntoT(_, _)
which in turn could be suppressed with @nowarn
.
However, to be honest in such cases when I know that I know better than the compiler - because code is trivial and obvious at a glance, and I also cover it with tests - .asInstanceOf
is not that bad. Sometimes you cannot avoid it so it's good to create some small, well tested utility which will help to deal with all cases where compiler was not so smart.