Union generic type without Either Scala

260 Views Asked by At

This works fine:

def echo[A, B](a: A, b: B): A = ???

This is also fine:

def echo[A, B](a: A, b: B): B = ???

However, how do we achieve this to return either type A or B?

// error
def echo[A, B](a: A, b: B): A|B = ???

Is it simply possible to have a union type of generic types A and B? Cheers.


UPDATE1

Either is an option but not ideal, as it requires a pattern match when processing the returned result. Effectively, I want this: A <: A|B, B <: A|B, which Either does not achieve.

Another extreme, I can do this, but type is too loose:

def echo[A, B](a: A, b: B): Any = ???

UPDATE2
Why I don't want Either?

(Reason 2)

The returned result would actually be a Dataset of Spark, which requires Encoder for any type that is not a subtype of Product (see this topic).

When calling this method many times, it ends up with too many Either wrapping each other, e.g. Either[Either[Either[...]]]. This requires too many encoders to be defined.

So I'm actually doing this:

def echo[A, B](a: A, b: B): Dataset[A|B] = ???

If I do this it would require to have many different encoders due to Either type:

def echo[A, B](a: A, b: B): Dataset[Either[A, B]] = ???
val result1: Either[Cat, Dog] = echo(a: Cat, b: Dog)
val result2: Either[Either[Cat, Dog], Pig] = echo(result1: Either[Cat, Dog], c: Pig)

// we have to define encoders:
implicit encoder1: org.apache.spark.sql.Encoders.kryo[Either[Cat, Dog]]
implicit encoder2: org.apache.spark.sql.Encoders.kryo[Either[Either[Cat, Dog], Pig]]

// if we keep iterating, then too many encoders to define...
1

There are 1 best solutions below

1
On

Soon-to-be-released Scala 3 has it.

def echo[A, B](a: A, b: B): A|B = ???  //this compiles

As can be seen in this Scastie session.