Skip to content

Instantly share code, notes, and snippets.

@tel
Created August 4, 2015 16:33
Show Gist options
  • Save tel/d0b8a7ace2bc0bbf3646 to your computer and use it in GitHub Desktop.
Save tel/d0b8a7ace2bc0bbf3646 to your computer and use it in GitHub Desktop.
Sums in Javascript
/*
"Concrete" sums are by default open. They are values of the form
{ variant: String, params: {[String]: *} }
*/
/**
* A very general (named) matcher for concrete sums.
*
* @invariant x : object
* @invariant x.variant : string
* @invariant x.params is a dictionary
* @invariant pat[x.variant] is callable
*/
function match(x, pat) { return pat[x.variant](x.params); }
/**
* Church encoding a concrete sum.
* @type {Sum -> Pattern[Sum] r -> r}
*/
function church(x) { return pat => match(x, pat); }
/*
Church encoding trades sums for products by encoding a sum as exactly its
matching behavior. This is a faithful encoding in a typed language.
We can also create "Church sums" directly by encoding a fragment of the
matching algorithm.
*/
function Just(a) { return pat => pat.Just({value: a}); }
function Nothing() { return pat => pat.Nothing({}); }
function matchChurch(pat) { return sum => sum(pat); }
/*
It's worth noting that in OO-mythos the Church encoded sum has been around
for a long time under the name "visitor pattern". In this case, sums are types
which accept visitation methods only and patterns are the visitors.
*/
/*
While the above system provides the explicitness and power of a normal typed sum system
it obviously is a bit weird for lacking types. In order for the above to work we must have
that patterns always "cover" the sums that they're matched against. This induces a
structural subtyping system on "open" sums which follows exactly from the "duck typing"
structural subtyping system on the regular Javascript objects which implement patterns.
Sum : Pattern -> Type
Sum pat = forall r . pat r -> r
Maybe a = Sum { Nothing: () -> r, Just: a -> r }
= { Nothing: () -> r, Just: a -> r } -> r
This expanded dynamics can be useful
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment