package scalaprops import scalaz._ import Or.{L, R} sealed abstract class Or sealed abstract class :-:[+H, +T <: Or] extends Or sealed abstract class OrConsInstances { implicit def order[H, T <: Or](implicit H: Order[H], T: Order[T]): Order[H :-: T] = Order.order{ case (L(a), L(b)) => H.order(a, b) case (R(a), R(b)) => T.order(a, b) case (R(_), L(_)) => Ordering.LT case (L(_), R(_)) => Ordering.GT } } object :-: extends OrConsInstances { implicit def equal[H, T <: Or](implicit H: Equal[H], T: Equal[T]): Equal[H :-: T] = Equal.equal{ case (L(a), L(b)) => H.equal(a, b) case (R(a), R(b)) => T.equal(a, b) case _ => false } } object Or { final case class L[+H, +T <: Or](head : H) extends :-:[H, T] { override def toString = head.toString } final case class R[+H, +T <: Or](tail : T) extends :-:[H, T] { override def toString = tail.toString } sealed trait Empty extends Or object Empty { implicit val instance: Order[Empty] = Order.order((_, _) => Ordering.EQ) } final class MkOr[C <: Or] private[Or] { def apply[T](t: T)(implicit inj: Inj[C, T]): C = inj(t) } def apply[C <: Or]: MkOr[C] = new MkOr[C] }