Sorting is a great triumph of functional programming
All rely on comparison, cmp :: a -> a -> bool

Herman Hollerith
Rely on exploiting the structure of the data

Fritz Henglein
sort :: Order v -> [v] -> [v]
sort :: forall v. Order k -> [(k,v)] -> [v]
sort :: forall v. Order k -> [(k,v)] -> [[v]]
sort _ [] = []
sort _ [(_, v)] = [[v]]
data Order t where
TrivO :: Order t
NatO :: Int -> Order Int
SumL :: Order t1 -> Order t2 -> Order (Either t1 t2)
ProdL :: Order t1 -> Order t2 -> Order (t1, t2)
MapO :: (t1 -> t2) -> Order t2 -> Order t1
ListL :: Order t -> Order [t]
sort TrivO xs = [[ v | (_, v) <- xs ]]
type Disc k = forall v. [(k,v)] -> [[v]]
sort :: Order k -> Disc k
sort (NatO n) xs = discNat n xs
discNat :: Int -> Disc Int
discNat n xs = filter (not . null) (bdiscNat n update xs)
update :: [v] -> v -> [v]
update vs v = v : vs
bdiscNat :: Int -> ([v] -> v -> [v]) -> [(Int, v)] -> [[v]]
bdiscNat (n :: Int) update xs =
map reverse (elems (accumArray update [] (0, n-1) xs))
SumL :: Order t1 -> Order t2 -> Order (Either t1 t2)
sort (SumL r1 r2) xs = sort r1 [ (k, v) | (Left k, v) <- xs ]
++ sort r2 [ (k, v) | (Right k, v) <- xs ]
ProdL :: Order t1 -> Order t2 -> Order (t1, t2)
sort (ProdL r1 r2) xs =
[ vs | ys <- sort r1 [ (k1,(k2,v)) | ((k1,k2), v) <-xs],
vs <- sort r2 ys ]
MapO :: (t1 -> t2) -> Order t2 -> Order t1
sort (MapO f r) xs = sort r [ (f k, v) | (k, v) <- xs ]
ListL :: Order t -> Order [t]
sort (ListL r) xs = sort (listL r) xs
listL :: Order t -> Order [t]
listL r = MapO fromList (SumL ordUnit (ProdL r (listL r)))
fromList :: [t] -> Either () (t, [t])
fromList [] = Left ()
fromList (x : xs) = Right (x, xs)
ordUnit :: Order ()
ordUnit = TrivO
ordNat8 :: Order Int
ordNat8 = NatO 255
ordInt32 :: Order Int
ordInt32 = MapO (splitW . (+ (-2147483648))) (ProdL ordNat16 ordNat16)
splitW :: Int -> (Int, Int)
splitW x = (shiftR x 16 .&. 65535, x .&. 65535)
ordChar8 :: Order Char
ordChar8 = MapO ord ordNat8
ordChar16 :: Order Char
ordChar16 = MapO ord ordNat16
ordString8 :: Order String
ordString8 = listL ordChar8
ordString16 :: Order String
ordString16 = listL ordChar16
listL r = MapO fromList (SumL ordUnit (ProdL r (listL r)))
fromList :: [t] -> Either () (t, [t])
fromList [] = Left ()
fromList (x : xs) = Right (x, xs)
let ws = ["AA","BCA","BA","BB","AAC","AB"]
sort $ zip ws ws
[["AA"],["AAC"],["AB"],["BA"],["BB"],["BCA"]]
-- If we'd input ["AA","BCA","BA","BB","AAC","AB"] ++ ["BCA"]
[["AA"],["AAC"],["AB"],["BA"],["BB"],["BCA","BCA"]]
abstract class Order[A]
case class TrivO[A]() extends Order[A]
case class NatO(i: Int) extends Order[Int]
case class SumL[A,B](t1: Order[A], t2: Order[B]) extends Order[Either[A,B]]
case class ProdL[A,B](t1: Order[A], t2: Order[B]) extends Order[(A,B)]
case class MapO[A,B](f: A => B, t2: Order[B]) extends Order[A]
case class ListL[A](t: Order[A]) extends Order[Stream[A]]
data Order t where
TrivO :: Order t
NatO :: Int -> Order Int
SumL :: Order t1 -> Order t2 -> Order (Either t1 t2)
ProdL :: Order t1 -> Order t2 -> Order (t1, t2)
MapO :: (t1 -> t2) -> Order t2 -> Order t1
ListL :: Order t -> Order [t]
val ordUnit = TrivO[Unit]()
val ordNat8 = NatO(255)
val ordInt32 = MapO(splitW º {x:Int => x+(-2147483648)}, ProdL(ordNat16, ordNat16))
def splitW: Int => (Int,Int) = x => ((x>>16) & 65535,x & 65535)
val ordChar8 = MapO({x: Char => x.toInt},ordNat8)
val ordString8 = ListL(ordChar8)
ordUnit = TrivO
ordNat8 = NatO 255
ordInt32 = MapO (splitW . (+ (-2147483648))) (ProdL ordNat16 ordNat16)
splitW x = (shiftR x 16 .&. 65535, x .&. 65535)
ordChar8 = MapO ord ordNat8
ordString8 = listL ordChar8
def sort[A,B](ord: Order[A], xs: Stream[(A,B)]): Stream[Stream[B]] =
xs match {
case Stream() => Stream()
case Stream((_,v)) => Stream(Stream(v))
case _ => ord match {
case TrivO() => Stream(xs map { _._2 })
case n: NatO => sortNat(n,xs)
case SumL(orda,ordb) => sortSum(orda,ordb,xs)
case ProdL(orda,ordb) => sortProd(orda,ordb,xs)
case MapO(f,ordb) => sortMap(f,ordb,xs)
case ListL(orda) => sortList(orda,xs)
}
}
def stripPartition[A](l: Stream[A]): (Either[Unit,(A,Stream[A])]) =
l.headOption.cata( { x: A => Right((x,l.tail)) }, { Left(()) } )
def sortList[A,B](orda: Order[A], xs: Stream[(Stream[A],B)]): Stream[Stream[B]] =
sort(MapO(stripPartition[A], SumL(ordUnit,ProdL(orda,ListL(orda)))), xs)
def sortMap[A,B,C](f: A => B, ordb: Order[B], xs: Stream[(A,C)]): Stream[Stream[C]] =
sort(ordb,xs map { case (a,c) => (f(a),c) })
def sortProd[A,B,C](orda: Order[A], ordb: Order[B], xs: Stream[((A,B),C)]): Stream[Stream[C]] =
sort(orda,xs map { case ((a,b),c) => (a,(b,c)) }) flatMap { sort(ordb,_) }
def sortSum[A,B,C](orda: Order[A], ordb: Order[B], xs: Stream[(Either[A,B],C)]): Stream[Stream[C]] = {
val (lefts,rights) = xs.foldRight((Stream[(A,C)](),Stream[(B,C)]())) {
case ((Left(x),v),(ls,rs)) => (ls :+ (x,v),rs)
case ((Right(x),v),(ls,rs)) => (ls,rs :+ (x,v))
}
sort(orda,lefts) ++ sort(ordb,rights)
}
def sortNat[A](z: NatO, xs: Stream[(Int,A)]): Stream[Stream[A]] = {
val arr = new Array[MutableList[A]](z.i+1)
xs.foreach { arg: (Int,A) =>
val idx = arg._1
if(arr(idx) == null) arr(idx) = MutableList[A](arg._2)
else arr(idx) += arg._2
}
arr.toStream.filter(_ != null).map(_.toStream)
}