Say I have a Cake that can cycle through a number of states:
sealed trait State extends Product with Serializable
object State {
final case object Raw extends State
final case class JustRight(temperature: Int) extends State
final case class Burnt(charCoalContent: Double) extends State
}
final case class Cake[S <: State](name: String, state: S)
This is nice, because now I can make sure that I only try to put Raw cakes into the oven, instead of eating them right away.
But sometimes I just have a Cake[State] lying around and want to try to eat it, but only if it's in an edible state. I could of course always pattern match on cake.state, but I thought it should be possible to save myself a few keystrokes by adding a method def narrow[S <: State]: Cake[State] => Option[Cake[S]].
However, now I'm struggling to actually implement that function. The compiler accepts Try(cake.asInstanceOf[Cake[S]]).toOption, but it seems that would always succeed (I guess because the type parameter is erased, and actually any type A would be accepted here, not just S). What seems to work is Try(cake.copy(state = cake.state.asInstanceOf[S])).toOption, but now I've made a superfluous copy of my data. Is there another better way? Or is that whole encoding maybe flawed from the get-go?