I'm trying to see if there is a way to find a type W2 that is the super type of 2 types W and E.
In my solution E represents errors, and W represents Warnings.
What I'm trying to accomplish is a method or that if this fails runs that and moves the error to the warning type.
Here is a simplified example of what I'm doing.
sealed trait Validator[-I, +E, +W, +A] extends Product with Serializable
this type has several cases, which aren't really important here, so instead I'll go over an example usage:
case class MyObj(coords: GeoCoords)
case class GeoCoords(lat: String, long: String)
        
// Getters
val getLatitude: Validator[GeoCoords, Nothing, Nothing, String] = from[GeoCoords].map(_.lat)
val getLongitude: Validator[GeoCoords, Nothing, Nothing, String] = from[GeoCoords].map(_.long)
val parseLatitude: Validator[GeoCoords, Exception, Nothing, Double] = getLatitude andThen nonEmptyString andThen convertToDouble
val parseLongitude: Validator[GeoCoords, Exception, Nothing, Double] = getLongitude andThen convertToDouble
Now this is a bad example, but what I'm looking to do is that because parseLatitude has an error type of Exception, perhaps I want to give a default instead, but still understand that it failed.  I'd like to move the Exception from the E error param to the W warning param like this:
val defaultLatitude: Validator[GeoCoords, Nothing, Nothing, Double] = success(0)
val finalLatitude: Validator[GeoCoords, Nothing, Exception, Double] = parseLatitude or defaultLatitude
But as well, if instead of supplying default, the other action I take after the or may fail as well, therefore this should also be the case:
val otherAction: Validator[GeoCoords, Throwable, Nothing, Double] = ???
val finalLatitude: Validator[GeoCoords, Throwable, Exception, Double] = parseLatitude or otherAction
I've tried implementing or in several ways on the Validator type but everytime it gives me an issue, basically casting things all the way up to Any.
def or[I2 <: I, E2 >: E, W2 >: W, B >: A](that: Validator[I2, E2, W2, B]): Validator[I2, E2, W2, B] = Validator.conversion { (i: I2) =>
  val aVal: Validator[Any, E, W, A] = this.run(i)
  val bVal: Validator[Any, E2, W2, B] = that.run(i)
  val a: Vector[W2] = aVal.warnings ++ bVal.warnings
  // PROBLEM HERE
  val b: Vector[Any] = a ++ aVal.errors
  Result(
    aVal.warnings ++ aVal.errors ++ bVal.warnings,
    bVal.value.toRight(bVal.errors)
  )
}
I need to be able to say that W2 is both a supertype of W and of E so that I can concatenate the Vectors together and get type W2 at the end.
A super simplified self contained example is:
case class Example[+A, +B](a: List[A], b: List[B]) {
  def or[A2 >: A, B2 >: B](that: Example[A2, B2]): Example[A2, Any] = {
    Example(that.a, this.a ++ this.b ++ that.a)
  }
}
object stackoverflow extends App {
  val example1 = Example(List(1, 2), List(3, 4))
  val example2 = Example(List(5, 6), List(7, 8))
  val example3 = example1 or example2
}
Where I want the output type of or to be Example[A2, B2] instead of Example[A2, Any]
 
    