Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Sorting, Seen Functionally

Sorting, Seen Functionally

Everyone knows sorting algorithms like bubble sort, insertion sort, selection sort, and quicksort. Maybe some already have an intuition that insertion and selection sort are closely related. This talk will dig into the details of folds and calculating with types. This sort of categorical, algebraic approach lets us think about algorithms and their specifications in a whole new light. In so doing, we will distill these sorts down to their essence, appreciating the duality that appears and specifying the mechanisms by which these different algorithms relate to one another.

Daniel James

April 23, 2014
Tweet

More Decks by Daniel James

Other Decks in Research

Transcript

  1. Sorting with Bialgebras and Distributive Laws Ralf Hinze, Daniel W.

    H. James, Thomas Harper, Nicholas Wu, and José Pedro Magalhães Workshop on Generic Programming, 2012, Copenhagen
  2. A Duality of Sorts Ralf Hinze, José Pedro Magalhães, and

    Nicholas Wu The Beauty of Functional Code, LNCS, 2012
  3. insert ⸬ Int → [Int] → [Int] insert y ys

    = xs ++ [y] ++ zs where (xs, zs) = span (< y) ys Insertion sort
  4. insertSort ⸬ [Int] → [Int] insertSort [] = [] insertSort

    (x:xs) = insert x ys where ys = insertSort xs Insertion sort
  5. foldr ⸬ (a → b → b) → b →

    [a] → b foldr f z [] = z foldr f z (x:xs) = f x (foldr f z xs) Reduce a list to a value
  6. select ⸬ [Int] → Maybe (Int, [Int]) select [] =

    Nothing select xs = Just (x, xs′) where x = minimum xs xs′ = delete x xs Selection Sort
  7. selectSort ⸬ [Int] → [Int] selectSort xs = case select

    xs of Nothing → [] Just (y, ys) → y : selectSort ys Selection Sort
  8. unfoldr ⸬ (b → Maybe (a,b)) → b → [a]

    unfoldr f b = case f b of Nothing → [] Just (a, b′) → a : unfoldr f b′ Build a list from a value
  9. repeat ⸬ a → [a] repeat a = a :

    repeat a Build a list from a value repeat a = unfoldr (\x → Just (x, x)) a
  10. iterate ⸬ (a → a) → a → [a] iterate

    f a = a : iterate f (f a) Build a list from a value iterate f a = unfoldr (\x → Just (x, f x)) a
  11. newtype Fix f = In { out ⸬ f (Fix

    f) } Recursive datatypes
  12. newtype Fix f = In { out ⸬ f (Fix

    f) } In ⸬ f (Fix f) → Fix f out ⸬ Fix f → f (Fix f) Recursive datatypes
  13. 1 : 2 : [] ≅ In (Cons 1 (In

    (Cons 2 (In Nil)))
  14. 1 : 2 : [] ≅ In (Cons 1 (In

    (Cons 2 (In Nil)))
  15. instance Functor List where fmap f Nil = Nil fmap

    f (Cons i list) = Cons i (f list)
  16. fold ⸬ (Functor f) 㱺 (f a → a) →

    Fix f → a fold g = g • fmap (fold g) • out Reduce a fix to a value Fix f -> f (Fix f) -> f a -> a ->
  17. fold ⸬ (Functor f) 㱺 (f a → a) →

    Fix f → a fold g (In Nil) Reduce a fix to a value = (g • fmap (fold g) • out) (In Nil) = (g • fmap (fold g)) Nil = g Nil
  18. fold ⸬ (Functor f) 㱺 (f a → a) →

    Fix f → a fold g (In (Cons i x)) Reduce a fix to a value = (g • fmap (fold g) • out) (In (Cons i x)) = (g • fmap (fold g)) (Cons i x) = g (Cons i (fold g x))
  19. unfold ⸬ (Functor f) 㱺 (a → f a) →

    a → Fix f unfold h = In • fmap (unfold h) • h Build a fix from a value a -> f a -> f (Fix f) -> Fix f ->
  20. Duality fold ⸬ (Functor f) 㱺 (f a → a)

    → Fix f → a unfold ⸬ (Functor f) 㱺 (a → f a) → a → Fix f
  21. Duality fold g = g • fmap (fold g) •

    out unfold h = In • fmap (unfold h) • h
  22. data List list = Nil | Cons Int list instance

    Functor List where fmap f Nil = Nil fmap f (Cons i list) = Cons i (f list) The shape of ordered lists of ints
  23. fold _ ⸬ Fix List → Fix List Calculating with

    types _ ⸬ List (Fix List) → Fix List
  24. fold (unfold _) ⸬ Fix List → Fix List Calculating

    with types unfold _ ⸬ List (Fix List) → Fix List
  25. fold (unfold _) ⸬ Fix List → Fix List Calculating

    with types unfold _ ⸬ List (Fix List) → Fix List _ ⸬ List (Fix List) → List (List (Fix List))
  26. naiveInsertSort ⸬ Fix List → Fix List naiveInsertSort = fold

    (unfold naiveInsert) Naïve insertion sort is a fold of an unfold
  27. naiveInsertSort ⸬ Fix List → Fix List naiveInsertSort = fold

    (unfold naiveInsert) naiveInsert ⸬ List (Fix List) → List (List (Fix List)) naiveInsert Nil = Nil naiveInsert (Cons i (In Nil)) = Cons i Nil naiveInsert (Cons i (In (Cons j x))) | i ⩽ j = Cons i (Cons j x) | otherwise = Cons j (Cons i x) Naïve insertion sort is a fold of an unfold
  28. unfold _ ⸬ Fix List → Fix List Calculating with

    types _ ⸬ Fix List → List (Fix List)
  29. unfold (fold _) ⸬ Fix List → Fix List Calculating

    with types fold _ ⸬ Fix List → List (Fix List)
  30. unfold (fold _) ⸬ Fix List → Fix List Calculating

    with types fold _ ⸬ Fix List → List (Fix List) _ ⸬ List (List (Fix List)) → List (Fix List)
  31. bubbleSort ⸬ Fix List → Fix List bubbleSort = unfold

    (fold bubble) Bubble sort is an unfold of a fold
  32. bubbleSort ⸬ Fix List → Fix List bubbleSort = unfold

    (fold bubble) bubble ⸬ List (List (Fix List)) → List (Fix List) bubble Nil = Nil bubble (Cons i Nil) = Cons i (In Nil) bubble (Cons i (Cons j x)) | i ⩽ j = Cons i (In (Cons j x)) | otherwise = Cons j (In (Cons i x)) Bubble sort is an unfold of a fold
  33. naiveInsert ⸬ List (Fix List) → List (List (Fix List))

    bubble ⸬ List (List (Fix List)) → List (Fix List) Awfully close…
  34. Awfully close… naiveInsert ⸬ List (Fix List) → List (List

    (Fix List)) naiveInsert Nil = Nil naiveInsert (Cons i (In Nil)) = Cons i Nil naiveInsert (Cons i (In (Cons j x))) | i ⩽ j = Cons i (Cons j x) | otherwise = Cons j (Cons i x)
  35. Awfully close… bubble ⸬ List (List (Fix List)) → List

    (Fix List) bubble Nil = Nil bubble (Cons i Nil) = Cons i (In Nil) bubble (Cons i (Cons j x)) | i ⩽ j = Cons i (In (Cons j x)) | otherwise = Cons j (In (Cons i x))
  36. naiveInsert ⸬ List (Fix List) → List (List (Fix List))

    bubble ⸬ List (List (Fix List)) → List (Fix List) Awfully close…
  37. naiveInsert ⸬ List (List (Fix List)) → List (List (Fix

    List)) bubble ⸬ List (List (Fix List)) → List (List (Fix List)) Awfully close…
  38. naiveInsert ⸬ List (List (Fix List)) → List (List (Fix

    List)) bubble ⸬ List (List (Fix List)) → List (List (Fix List)) Awfully close…
  39. swap ⸬ List (List x) → List (List x) swap

    Nil = Nil swap (Cons i Nil) = Cons i Nil swap (Cons i (Cons j x)) | i ⩽ j = Cons i (Cons j x) | otherwise = Cons j (Cons i x) A step function
  40. naiveInsertSort, bubbleSort ⸬ Fix List → Fix List bubbleSort =

    unfold (fold (fmap In • swap)) naiveInsertSort = fold (unfold (swap • fmap out))
  41. 2 5 4 1 3 2 5 4 1 3

    2 5 4 1 3 2 5 1 3 4 2 1 3 4 5 1 2 3 4 5 input output Naïve insertion sort
  42. 2 5 4 1 3 1 2 5 4 3

    1 2 3 5 4 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 input output Bubble sort
  43. para ⸬ (Functor f) 㱺 (f (Fix f × a)

    → a) → Fix f → a More expressive power fold ⸬ (Functor f) 㱺 (f a → a) → Fix f → a
  44. unfold ⸬ (Functor f) 㱺 (a → f a) →

    a → Fix f More expressive power apo ⸬ (Functor f) 㱺 (a → f (Fix f + a)) → a → Fix f
  45. swop ⸬ List (List× x) → List (List+ x) swop

    Nil = Nil swop (Cons i (x @ Nil)) = Cons i (Stop x) swop (Cons i (x @ Cons j y)) | i ⩽ j = Cons i (Stop x) | otherwise = Cons j (Go (Cons i y)) An improved step function
  46. insertSort, selectSort ⸬ Fix List → Fix List selectSort =

    unfold (para (____ • swop)) insertSort = fold (apo (swop • ____))
  47. quickSort, treeSort ⸬ Fix List → Fix List grow ⸬

    Fix List → Fix SearchTree flatten ⸬ Fix SearchTree → Fix List
  48. heapSort, mingleSort ⸬ Fix List → Fix List pile ⸬

    Fix List → Fix Heap sift ⸬ Fix Heap → Fix List