Skip to content

Instantly share code, notes, and snippets.

@DmytroMitin
Last active October 6, 2018 13:17
Show Gist options
  • Save DmytroMitin/03e3dd24fe5b0241eb62b34452dbb9bd to your computer and use it in GitHub Desktop.
Save DmytroMitin/03e3dd24fe5b0241eb62b34452dbb9bd to your computer and use it in GitHub Desktop.
object App {
trait Subtype[A, B] {
type C <: B
def apply(ev: A <:< B): (C =:= A, A =:= C)
}
object Subtype {
type Aux[A, B, C0 <: B] = Subtype[A, B] { type C = C0 }
def instance[A, B, C0 <: B](f: A <:< B => (C0 =:= A, A =:= C0)): Aux[A, B, C0] = new Subtype[A, B] {
override type C = C0
override def apply(ev: A <:< B): (C0 =:= A, A =:= C0) = f(ev)
}
def materialize[A, B](implicit subtype: A Subtype B): Aux[A, B, subtype.C] = subtype
def materialize1[A, B](ev: A <:< B)(implicit subtype: A Subtype B): Aux[A, B, subtype.C] = subtype
implicit def mkSubtype[A, B >: A]: Aux[A, B, A] = instance(_ => (implicitly, implicitly))
}
val x = Subtype.materialize[Int, AnyVal]
implicitly[x.C <:< AnyVal]
x(implicitly)._1: x.C =:= Int
x(implicitly)._2: Int =:= x.C
def test[A, B, C <: B] = ???
test[Int, AnyVal, x.C]
val y = Subtype.materialize1(implicitly[Int <:< AnyVal])
implicitly[y.C <:< AnyVal]
y(implicitly)._1: y.C =:= Int
y(implicitly)._2: Int =:= y.C
test[Int, AnyVal, y.C]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment