```package scalaz

trait Order[-A] extends Equal[A] {
def order(a1: A, a2: A): Ordering

final def equal(a1: A, a2: A): Boolean = order(a1, a2) == EQ
}

trait Orders {
import Scalaz._

def order[A](f: (A, A) => Ordering): Order[A] = new Order[A] {
def order(a1: A, a2: A) = f(a1, a2)
}

def orderBy[A, B: Order](f: A => B): Order[A] = implicitly[Order[B]] ∙ f

}

trait OrderLow {
import Scalaz._

implicit def ScalaOrderingOrder[T: scala.Ordering]: Order[T] = order {(t1, t2) =>
implicitly[scala.Ordering[T]].compare(t1, t2) match {
case -1 => LT
case 0 => EQ
case 1 => GT
}
}
}

object Order {
import Scalaz._
import java.math.BigInteger

implicit def DigitOrder: Order[Digit] = orderBy(_.toInt)

implicit def OrderingOrder: Order[Ordering] = order {
case (a, EQ) => a
case (EQ, LT) => GT
case (EQ, GT) => LT
case (LT, LT) => EQ
case (LT, _) => LT
case (GT, GT) => EQ
case (GT, _) => GT
}

implicit def OrderOrdering[A: Order]: scala.Ordering[A] = new scala.Ordering[A] {
def compare(a1: A, a2: A) = (a1 ?|? a2) match {
case EQ => 0
case LT => -1
case GT => 1
}
}

implicit def UnitOrder: Order[Unit] = order((_, _) => EQ)

implicit def StringOrder: Order[String] = order((a1, a2) => if (a1 > a2) GT else if (a1 < a2) LT else EQ)

implicit def SymbolOrder: Order[Symbol] = orderBy(_.name)

implicit def IntOrder: Order[Int] = order((a1, a2) => if (a1 > a2) GT else if (a1 < a2) LT else EQ)

implicit def IntMultiplicationOrder: Order[IntMultiplication] = orderBy(_.value)

implicit def BooleanOrder: Order[Boolean] = order((a1, a2) => if (a1 > a2) GT else if (a1 < a2) LT else EQ)

implicit def BooleanConjunctionOrder: Order[BooleanConjunction] = orderBy(_.value)

implicit def CharOrder: Order[Char] = order((a1, a2) => if (a1 > a2) GT else if (a1 < a2) LT else EQ)

implicit def CharMultiplicationOrder: Order[CharMultiplication] = orderBy(_.value)

implicit def ByteOrder: Order[Byte] = order((a1, a2) => if (a1 > a2) GT else if (a1 < a2) LT else EQ)

implicit def ByteMultiplicationOrder: Order[ByteMultiplication] = orderBy(_.value)

implicit def LongOrder: Order[Long] = order((a1, a2) => if (a1 > a2) GT else if (a1 < a2) LT else EQ)

implicit def LongMultiplicationOrder: Order[LongMultiplication] = orderBy(_.value)

implicit def ShortOrder: Order[Short] = order((a1, a2) => if (a1 > a2) GT else if (a1 < a2) LT else EQ)

implicit def ShortMultiplicationOrder: Order[ShortMultiplication] = orderBy(_.value)

implicit def FloatOrder: Order[Float] = order((a1, a2) => if (a1 > a2) GT else if (a1 < a2) LT else EQ)

implicit def DoubleOrder: Order[Double] = order((a1, a2) => if (a1 > a2) GT else if (a1 < a2) LT else EQ)

implicit def BigIntegerOrder: Order[BigInteger] = order(_ compareTo _ ordering)

implicit def BigIntegerMultiplicationOrder: Order[BigIntegerMultiplication] = orderBy(_.value)

implicit def BigIntOrder: Order[BigInt] = order((a1, a2) => if (a1 > a2) GT else if (a1 < a2) LT else EQ)

implicit def BigIntMultplicationOrder: Order[BigIntMultiplication] = orderBy(_.value)

implicit def NonEmptyListOrder[A: Order]: Order[NonEmptyList[A]] = orderBy(_.list)

implicit def ZipStreamOrder[A: Order]: Order[ZipStream[A]] = orderBy(_.value)

implicit def Tuple1Order[A: Order]: Order[Tuple1[A]] = order(_._1 ?|? _._1)

implicit def IndSeqOrder[A: Order]: Order[IndSeq[A]] = orderBy(_.toList)

import Foldable._

implicit def Tuple2Order[A: Order, B: Order]: Order[(A, B)] = order {
case ((a1, b1), (a2, b2)) => ListFoldable.fold(List(a1 ?|? a2, b1 ?|? b2))
}

implicit def Tuple3Order[A: Order, B: Order, C: Order]: Order[(A, B, C)] = order {
case ((a1, b1, c1), (a2, b2, c2)) => ListFoldable.fold(List(a1 ?|? a2, b1 ?|? b2, c1 ?|? c2))
}

implicit def Tuple4Order[A: Order, B: Order, C: Order, D: Order]: Order[(A, B, C, D)] = order {
case ((a1, b1, c1, d1), (a2, b2, c2, d2)) => ListFoldable.fold(List(a1 ?|? a2, b1 ?|? b2, c1 ?|? c2, d1 ?|? d2))
}

implicit def Tuple5Order[A: Order, B: Order, C: Order, D: Order, E: Order]: Order[(A, B, C, D, E)] = order {
case ((a1, b1, c1, d1, e1), (a2, b2, c2, d2, e2)) => ListFoldable.fold(List(a1 ?|? a2, b1 ?|? b2, c1 ?|? c2, d1 ?|? d2, e1 ?|? e2))
}

implicit def Tuple6Order[A: Order, B: Order, C: Order, D: Order, E: Order, F: Order]: Order[(A, B, C, D, E, F)] = order {
case ((a1, b1, c1, d1, e1, f1), (a2, b2, c2, d2, e2, f2)) => ListFoldable.fold(List(a1 ?|? a2, b1 ?|? b2, c1 ?|? c2, d1 ?|? d2, e1 ?|? e2, f1 ?|? f2))
}

implicit def Tuple7Order[A: Order, B: Order, C: Order, D: Order, E: Order, F: Order, G: Order]: Order[(A, B, C, D, E, F, G)] = order {
case ((a1, b1, c1, d1, e1, f1, g1), (a2, b2, c2, d2, e2, f2, g2)) => ListFoldable.fold(List(a1 ?|? a2, b1 ?|? b2, c1 ?|? c2, d1 ?|? d2, e1 ?|? e2, f1 ?|? f2, g1 ?|? g2))
}

implicit def Function0Order[A: Order]: Order[() => A] = order(_.apply ?|? _.apply)

implicit def IterableOrder[A: Order]: Order[Iterable[A]] = order((a1, a2) => {
val i1 = a1.iterator
val i2 = a2.iterator
var b = true
var r: Ordering = EQ

while (i1.hasNext && i2.hasNext && b) {
val a1 = i1.next
val a2 = i2.next

val o = a1 ?|? a2
if (o != EQ) {
r = o
b = false
}
}

if (i1.hasNext)
if (i2.hasNext)
r
else
GT
else
LT
})

implicit def OptionOrder[A: Order]: Order[Option[A]] = order {
case (Some(x), Some(y)) => x ?|? y
case (Some(_), None) => GT
case (None, Some(_)) => LT
case (None, None) => EQ
}

implicit def EitherOrder[A: Order, B: Order]: Order[Either[A, B]] = order {
case (Left(x), Left(y)) => x ?|? y
case (Right(x), Right(y)) => x ?|? y
case (Left(_), Right(_)) => LT
case (Right(_), Left(_)) => GT
}

implicit def EitherLeftOrder[A: Order, B]: Order[Either.LeftProjection[A, B]] = order((a1, a2) =>
(a1.toOption, a2.toOption) match {
case (Some(a1), Some(a2)) => a1 ?|? a2
case (Some(_), None) => GT
case (None, Some(_)) => LT
case (None, None) => EQ
})

implicit def EitherRightOrder[A, B: Order]: Order[Either.RightProjection[A, B]] = order((b1, b2) =>
(b1.toOption, b2.toOption) match {
case (Some(b1), Some(b2)) => b1 ?|? b2
case (Some(_), None) => GT
case (None, Some(_)) => LT
case (None, None) => EQ
})

implicit def ValidationOrder[E: Order, A: Order]: Order[Validation[E, A]] = orderBy(_.either)

implicit def JavaIterableOrder[A: Order]: Order[java.lang.Iterable[A]] = {
import collection.JavaConversions._
IterableOrder[A] ∙ (x => x)
}
}

```