I would like to have a A|B type to be the subtype of A|B|C. Is that possible to encode in Scala ? If yes, how ?
I was hoping that I can make implicitly[¬¬[IF] <:< T] compile below (original code here), but it does not. Is there a way to fix this code to allow subtyping ?
object NUnion{
  type ¬¬[A] = ¬[¬[A]]
  type ¬[A] = A => Nothing
  trait Disj[T] {
    type or[S] = Disj[T with ¬[S]]
    type apply = ¬[T]
  }
  // for convenience
  type disj[T] = { type or[S] = Disj[¬[T]]#or[S] }
  type T = disj[Int]#or[Float]#or[String]#apply
  type IF = disj[Int]#or[Float]#apply
  implicitly[¬¬[Int] <:< T] // works
  // implicitly[¬¬[Double] <:< T] // doesn't work
  // implicitly[¬¬[IF] <:< T] // doesn't work - but it should
}
I also tried this (from here):
object Kerr{
  def f[A](a: A)(implicit ev: (Int with String with Boolean) <:< A) = a match {
     case i: Int => i + 1
     case s: String => s.length
  }
  f(1) //works
  f("bla") // works
  def g[R]()(implicit ev: (Int with String with Boolean) <:< R):R = "go" // does not work
}
but here I cannot make a union type "first-class" they can only exist as argument types, not as return types.
Same problem with this approach :
object Map{
  object Union {
    import scala.language.higherKinds
    sealed trait ¬[-A]
    sealed trait TSet {
      type Compound[A]
      type Map[F[_]] <: TSet
    }
    sealed trait ∅ extends TSet {
      type Compound[A] = A
      type Map[F[_]] = ∅
    }
    // Note that this type is left-associative for the sake of concision.
    sealed trait ∨[T <: TSet, H] extends TSet {
      // Given a type of the form `∅ ∨ A ∨ B ∨ ...` and parameter `X`, we want to produce the type
      // `¬[A] with ¬[B] with ... <:< ¬[X]`.
      type Member[X] = T#Map[¬]#Compound[¬[H]] <:< ¬[X]
      // This could be generalized as a fold, but for concision we leave it as is.
      type Compound[A] = T#Compound[H with A]
      type Map[F[_]] = T#Map[F] ∨ F[H]
    }
    def foo[A : (∅ ∨ String ∨ Int ∨ List[Int])#Member](a: A): String = a match {
      case s: String => "String"
      case i: Int => "Int"
      case l: List[_] => "List[Int]"
    }
    def geza[A : (∅ ∨ String ∨ Int ∨ List[Int])#Member] : A = "45" // does not work 
    foo(geza)
    foo(42)
    foo("bar")
    foo(List(1, 2, 3))
//    foo(42d) // error
//    foo[Any](???) // error
  }
}
 
     
    