Skip to content

Instantly share code, notes, and snippets.

@jbgi
Created September 25, 2018 14:51
Show Gist options
  • Save jbgi/e94616fa193e5da7b1f105dba947ddb5 to your computer and use it in GitHub Desktop.
Save jbgi/e94616fa193e5da7b1f105dba947ddb5 to your computer and use it in GitHub Desktop.
Zero-cost, subtyping-free conversion from product type to sum type
sealed trait Option[A]
sealed abstract case class Some[A](value: A) extends Option[A]
sealed abstract case class None[A]() extends Option[A]
sealed trait Id[A] { self: Option[A] =>
final def toOption: Option[A] = this
def value: A
}
object Id {
def apply[A](value: A) = new Some[A](value) with Id[A] {}
def unapply[A](id: Id[A]) = new Unapply(id.value)
final class Unapply[A](val value: A) extends AnyVal {
def isEmpty = false
def get = value
}
}
object Some {
def apply[A](value: A): Option[A] = Id(value).toOption
}
object None {
private[this] val None = new None[Nothing]() {}
def apply[A]: Option[A] = None.asInstanceOf[Option[A]]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment