Skip to content

Instantly share code, notes, and snippets.

@wheaties
Created March 17, 2016 00:28
type |[A, B] = (A, B)
trait OneOfProof[Obj, Items]{
type Value <: Bool
}
object OneOfProof extends LowPriorityOneOf{
def apply[Obj, Items](implicit oneOf: OneOfProof[Obj, Items]): Aux[Obj, Items, oneOf.Value] = oneOf
implicit def left[L, R, Obj <: L]: Aux[Obj, L | R, True] = new OneOfProof[Obj, L | R]{
type Value = True
}
}
trait LowPriorityOneOf extends LowPriorityOneOf1{
implicit def right[L, R, Obj <: R]: Aux[Obj, L | R, True] = new OneOfProof[Obj, L | R]{
type Value = True
}
}
trait LowPriorityOneOf1 extends LowPriorityOneOf2{
implicit def recur[L, R, Obj](implicit oneOf: OneOf[Obj, R]): Aux[Obj, L | R, oneOf.Value] =
new OneOfProof[Obj, L | R]{
type Value = oneOf.Value
}
}
trait LowPriorityOneOf2{
type Aux[O, I, B <: Bool] = OneOfProof[O, I]{ type Value = B }
implicit def not[O, I]: Aux[O, I, False] = new OneOfProof[O, I]{
type Value = False
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment