packages feed

MiniAgda-0.2014.1.9: test/succeed/quicksort.ma

-- 2010-06-21 Andreas Abel  
-- Quicksort (implementation using partition) in MiniAgda
-- more efficient implementation see qsapp.ma

-- Booleans

data Bool : Set
{ true : Bool
; false : Bool
}

fun if : [A : Set] -> Bool -> A -> A -> A
{ if A true  t e = t
; if A false t e = e
}

-- Natural numbers

data Nat : Set
{ zero : Nat
; succ : Nat -> Nat
}

fun leq : Nat -> Nat -> Bool 
{ leq  zero     n       = true
; leq (succ m)  zero    = false
; leq (succ m) (succ n) = leq m n
}

-- Lists over natural numbers as a sized inductive type

sized data List : Size -> Set
{ nil  : [i : Size] -> List ($ i) 
; cons : [i : Size] -> Nat -> List i -> List ($ i)
}

-- Append lists (yields no size information)

fun append : List # -> List # -> List #
{ append (nil .#)       l = l
; append (cons .# x xs) l = cons # x (append xs l)
}

-- Partition a list, continuation-style

fun partition : (Nat -> Bool) -> [i : Size] -> List i -> 
  [A : Set] -> (List i -> List i -> A) -> A
{ partition p i (nil  (i > j))     A k = k (nil j) (nil j)
; partition p i (cons (i > j) n l) A k = if A (p n)
   (partition p j l A (\ l1 -> \ l2 -> k (cons j n l1) l2)) -- then 
   (partition p j l A (\ l1 -> \ l2 -> k l1 (cons j n l2))) -- else
}

-- Quicksort 

fun quicksort : [i : Size] -> List i -> List #
{ quicksort i (nil  (i > j))     = nil j
; quicksort i (cons (i > j) n l) = partition (\ m -> leq m n) j l (List #)
    (\ l1 -> \ l2 -> append (quicksort j l1) (cons # n (quicksort j l2)))
}

-- Testing

let n0 : Nat = zero
let n1 : Nat = succ n0
let n2 : Nat = succ n1
let n3 : Nat = succ n2
let n4 : Nat = succ n3
let n5 : Nat = succ n4
let n6 : Nat = succ n5
let n7 : Nat = succ n6
let n8 : Nat = succ n7
let n9 : Nat = succ n8

{- MiniAgda CBN is too inefficient to do this in reasonable time
let l : List # = 
  (cons # 4 (cons # 9 (cons # 1 (cons # 7 (cons # 6 
  (cons # 4 (cons # 0 (cons # 0 
  (cons # 3 (cons # 3 (cons # 3 (cons # 2 (cons # 3 (nil #))))))))))))))
-}
let l : List # = cons # n1 (cons # n3 (cons # n0 (cons # n2 (nil #))))
eval let l' : List # = quicksort # l