How does one narrow down from a union type to one of the component types in a for comprehension?
I’m trying to convert from using an Option of some (concrete) type T to using a union type that “unions” a type representing being empty with that original type T. (See OldCellState
vs. NewCellState
in the code below.)
Specifically, I’m trying to convert the logic at the line labeled with “#1” (a for-comprehension generator(?) that limits processing to only non-empty cell and gets the ball color in a variable for further use).
What the right/normal/usual way to convert that for a union type?
My conversion attempt at the line labeled “#2” fails compilation with the error message “value withFilter is not a member of Example.NewCellState”. I partially understand that desugaring a for comprehension can involve a withFilter
call, but I don’t even know if I’m on the right starting path here.
object Example {
enum BallColor { case Black, White }
type OldCellState = Option[BallColor]
case object Empty
type NewCellState = Empty.type | BallColor
val oldCellStates: List[OldCellState] = ???
val newCellStates: List[NewCellState] = ???
for {
oldCellState <- oldCellStates
ballColor <- oldCellState // #1
} yield ballColor: BallColor
for {
newCellState <- newCellStates
// "value withFilter is not a member of Example.NewCellState":
case ballColor @ BallColor <- newCellState // #2
} yield ballColor: BallColor
for {
newCellState <- newCellStates
ballColor <- // #3
newCellState match
case Empty => None
case color: BallColor => Some(color)
} yield ballColor: BallColor
}
I can get things to work by using the approach labeled “#3”, it seems that there’s got to be a less verbose way than that.
(Additionally, #3 defeats one purpose for using the union type in the first place–to eliminate allocating a Some
instance wrapping a BallColor
for each non-empty cell. It really defeats that purpose, since it allocates (or seems to) a Some
instance for each execution of that code for a non-empty cell (and, in the project this is extracted from, there’ll be a lot more executions of that code than the number of cells).)
So, any suggestions?
Thanks.