Skip to content

Instantly share code, notes, and snippets.

@scott-christopher
Created December 4, 2016 03:23
Show Gist options
  • Save scott-christopher/c0e76689c40988ce4e08fca4fe97d7dd to your computer and use it in GitHub Desktop.
Save scott-christopher/c0e76689c40988ce4e08fca4fe97d7dd to your computer and use it in GitHub Desktop.
Hylo MergeSort
// recursively deconstruct a functor by the given `alg` function
const cata = alg => x => alg(x.map(cata(alg)))
// recursively construct a functor by the given `coAlg` function
const ana = coAlg => x => coAlg(x).map(ana(coAlg))
// `hylo(alg, coAlg)` equivalent to `compose(cata(alg), ana(coAlg))`
// performed in a single pass
const hylo = (alg, coAlg) => function go(x) {
return alg(coAlg(x).map(go))
}
// constructors representing a binary tree
const Empty =
({ map: returnThis, match: cases => cases['Empty']() })
const Leaf = x =>
({ map: returnThis, match: cases => cases['Leaf'](x) })
const Node = (l, r) =>
({ map: f => Node(f(l), f(r)), match: cases => cases['Node'](l, r) })
function returnThis() { return this }
// non-recursive transformation of a list to a tree
const listToTree = (xs) =>
xs.length === 0 ? Empty :
xs.length === 1 ? Leaf(xs[0]) :
Node(xs.slice(0, xs.length / 2),
xs.slice(xs.length / 2))
// non-recursive transformation of a tree to a sorted list
const treeToList = tree => tree.match({
Empty: () => [],
Leaf: (x) => [x],
Node: mergeLists
})
// merge two sorted lists together
const mergeLists = (xs, ys) =>
xs.length === 0 ? ys :
ys.length === 0 ? xs :
xs[0] <= ys[0] ? [xs[0], ...mergeLists(xs.slice(1), ys)] :
[ys[0], ...mergeLists(xs, ys.slice(1))]
const mergeSort = hylo(treeToList, listToTree)
mergeSort([2, 1, 4, 3, 0])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment