{-# LANGUAGE ImplicitParams #-}
-- Enable the implicit parameters language extension.
import Data.Function (on)
-- Declare a generic sort function which takes a comparator.
sortBy :: (a -> a -> Ordering) -> [a] -> [a]
sortBy _ [] = []
sortBy cmp (p:xs) = sortBy cmp (filter ((== GT) . cmp p) xs) ++ [p] ++ sortBy cmp (filter ((/= GT) . cmp p) xs)
-- Declare a sort function to sort a list.
sort :: (?cmp :: a -> a -> Ordering) => [a] -> [a]
sort = sortBy ?cmp
main :: IO ()
main = do
let xs = [(1, 42), (5, 8), (10, 4), (3, 14), (15, 92)]
let ?cmp = compare `on` fst
-- All equivalent: [(1,42),(3,14),(5,8),(10,4),(15,92)]
putStrLn "--- 1 ---"
print $ sortBy (compare `on` fst) xs
print $ sortBy ?cmp xs
print $ sort xs
-- Change comparator. [(15,92),(1,42),(3,14),(5,8),(10,4)]
putStrLn "--- 2 ---"
let ?cmp = compare `on` (negate . snd)
print $ sortBy ?cmp xs
print $ sort xs
let ?cmp2 = compare `on` snd
putStrLn "--- 3 ---"
print $ sortBy ?cmp2 xs
print $ sort xs -- Which one is implicitly passed? `cmp` or `cmp2`? :)
return ()