-
-
Save edwinb/46da18e2fc6be3f92177ea02ea4b3a1a to your computer and use it in GitHub Desktop.
merge sort, totally, no cheating
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Control.WellFounded | |
import Data.List | |
smaller : List a -> List a -> Type | |
smaller xs ys = LT (length xs) (length ys) | |
ltS : LTE (S x) y -> LTE x y | |
ltS (LTESucc x) = lteSuccRight x | |
total | |
ltTrans : LTE n m -> LTE m p -> LTE n p | |
ltTrans LTEZero y = LTEZero | |
ltTrans (LTESucc x) (LTESucc y) = LTESucc (ltTrans x y) | |
ltZimpossible : (x : smaller xs []) -> Accessible smaller xs | |
ltZimpossible LTEZero impossible | |
ltZimpossible (LTESucc _) impossible | |
total | |
smallerAcc : (ys : List a) -> smaller xs ys -> Accessible smaller xs | |
smallerAcc [] x = ltZimpossible x | |
smallerAcc (y :: ys) (LTESucc x) | |
= Access (\val, p => smallerAcc ys (ltTrans p x)) | |
data Split : List a -> Type where | |
SplitNil : Split [] | |
SplitOne : Split [x] | |
SplitPair : Split (x :: xs ++ y :: ys) | |
splitHelp : (head : a) -> | |
(xs : List a) -> | |
(counter : List a) -> Split (head :: xs) | |
splitHelp head [] counter = SplitOne | |
splitHelp head (x :: xs) [] = SplitPair {xs = []} {ys = xs} | |
splitHelp head (x :: xs) [y] = SplitPair {xs = []} {ys = xs} | |
splitHelp head (x :: xs) (_ :: _ :: ys) | |
= case splitHelp head xs ys of | |
SplitOne => SplitPair {xs = []} {ys = []} | |
SplitPair {xs} {ys} => SplitPair {xs = (x :: xs)} {ys = ys} | |
split : (xs : List a) -> Split xs | |
split [] = SplitNil | |
split (x :: xs) = splitHelp x xs xs | |
data SplitRec : List a -> Type where | |
SplitRecNil : SplitRec [] | |
SplitRecOne : SplitRec [x] | |
SplitRecPair : Lazy (SplitRec xs) -> Lazy (SplitRec ys) -> SplitRec (xs ++ ys) | |
lengthSuc : (xs : List a) -> (y : a) -> (ys : List a) -> | |
length (xs ++ (y :: ys)) = S (length (xs ++ ys)) | |
lengthSuc [] _ _ = Refl | |
lengthSuc (x :: xs) y ys = cong (lengthSuc xs y ys) | |
lengthLT : (xs : List a) -> (ys : List a) -> | |
LTE (length xs) (length (ys ++ xs)) | |
lengthLT xs [] = lteRefl | |
lengthLT xs (x :: ys) = lteSuccRight (lengthLT _ _) | |
smallerLeft : (ys : List a) -> (y : a) -> (zs : List a) -> | |
LTE (S (S (length ys))) (S (length (ys ++ (y :: zs)))) | |
smallerLeft [] y zs = LTESucc (LTESucc LTEZero) | |
smallerLeft (z :: ys) y zs = LTESucc (smallerLeft ys _ _) | |
smallerRight : (ys : List a) -> (zs : List a) -> | |
LTE (S (S (length zs))) (S (length (ys ++ (y :: zs)))) | |
smallerRight {y} ys zs = rewrite lengthSuc ys y zs in | |
(LTESucc (LTESucc (lengthLT _ _))) | |
total | |
splitRecFix : (xs : List a) -> ((ys : List a) -> smaller ys xs -> SplitRec ys) -> | |
SplitRec xs | |
splitRecFix xs srec with (split xs) | |
splitRecFix [] srec | SplitNil = SplitRecNil | |
splitRecFix [x] srec | SplitOne = SplitRecOne | |
splitRecFix (x :: (ys ++ (y :: zs))) srec | SplitPair | |
= let left = srec (x :: ys) (smallerLeft ys y zs) | |
right = srec (y :: zs) (smallerRight ys zs) in | |
SplitRecPair left right | |
total | |
splitRec : (xs : List a) -> SplitRec xs | |
splitRec [] = SplitRecNil | |
splitRec (x :: xs) = accInd splitRecFix (x :: xs) (smallerAcc (x :: x :: xs) lteRefl) | |
-- Show all the splits for all the recursive calls, to demonstrate they really | |
-- are split in half | |
showDivisions : (xs : List a) -> List (List a) | |
showDivisions xs with (splitRec xs) | |
showDivisions [] | SplitRecNil = [] | |
showDivisions [x] | SplitRecOne = [[x]] | |
showDivisions (ys ++ zs) | (SplitRecPair ysrec zsrec) = | |
(ys ++ zs) :: showDivisions ys | ysrec ++ | |
showDivisions zs | zsrec | |
total | |
mergeSort : Ord a => List a -> List a | |
mergeSort xs with (splitRec xs) | |
mergeSort [] | SplitRecNil = [] | |
mergeSort [x] | SplitRecOne = [x] | |
mergeSort (ys ++ zs) | SplitRecPair ysrec zsrec | |
= merge (mergeSort ys | ysrec) | |
(mergeSort zs | zsrec) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment