Type-level removal of one type from an arbitrary type union

Viewed 52

If I have an arbitrary type union in Scala 3, is it possible to write a method that "removes" one type from the union?

Similar to shapeless.ops.coproduct.Remove, but for native Scala 3.

For example, if I have a union type representing a handful of different errors, and I want to write a function that recovers from one specific error type and leave the remaining errors as a new union type.

val result: Either[Foo | Bar | Baz | Bang, Thing]
val otherResult: Either[Foo | Bar, OtherThing]

// pretend syntax
def recoverBar[X, A](error: Bar | ...X)(f: Bar => A): Either[X, A] = 
  error match {
    case e: Bar => Right(f(e))
    case otherError => Left(otherError)
  }

// example usage
val recoveredResult: Either[Foo | Baz | Bang, Option[Thing]] = result
  .map { Option.apply }
  .left.flatMap { recoverBar(_)(_ => None) }

val recoveredOther: Either[Foo, OtherThing] = otherResult
  .left.flatMap { recoverBar(_)(_ => OtherThing.default) }

I.e. some kind of type-level generic way to do

[Foo | Bar | Baz | Bang] =>> [Foo | Baz | Bang]
[Foo | Bar] =>> [Foo]
[Bar] =>> [Nothing]
0 Answers
Related