Is it possible to make a type-alias (or something equivalent) in Scala that takes two parameters and returns their common supertype? In other words, I\'m trying to find some
I can give you a trait CommonSupertype[A, B] and an implicit generator function, so you can just require an implicit instance of this trait wherever you need it, and it will contain the common supertype (as a dependent type).
This is not my idea, it's actually adapted ever so slightly from this post by Miles Sabin.
The only change I've made is that, while he is using ¬¬[C] <:< (A ∨ B) as evidence that a type C is a subtype of either A or B, I've reversed the subtyping direction (so: (A ∨ B) <:< ¬¬[C]) to check that both A and B are subtypes of C.
import scala.reflect.ClassTag
object Main extends App {
type ¬[A] = A => Nothing
type ∨[T, U] = ¬[¬[T] with ¬[U]]
type ¬¬[A] = ¬[¬[A]]
trait CommonSupertype[A, B] {
type λ
def tag: ClassTag[λ]
}
// The ClassTag is only so I can get ahold of the type's name at runtime
implicit def commonSupertype[A, B, C : ClassTag](implicit C: (A ∨ B) <:< ¬¬[C]): CommonSupertype[A, B] { type λ = C } =
new CommonSupertype[A, B] { type λ = C; def tag = implicitly[ClassTag[C]] }
trait Pet
class Dog extends Pet
class Cat extends Pet
def check[A, B](implicit x: CommonSupertype[A, B]) = {
// This just prints the common type, but you could use the type (x.λ) directly
println(x.tag.toString())
}
check[Dog, Cat]
check[Dog, Double]
}
Gives us:
Main.Pet
Any