Last active
August 20, 2017 18:45
-
-
Save zkbpkp/9684e99239beca35dd2ed27e6e5104de to your computer and use it in GitHub Desktop.
This file contains hidden or 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
const tag = Symbol(); | |
const data = (variants, extend = class {}) => { | |
const obj = class extends extend {}; | |
for (const v in variants) { | |
let cargs; | |
obj[v] = (...args) => new (class extends obj { | |
constructor(...args) { | |
super(); | |
cargs = args; | |
this[tag] = v; | |
for (let i = 0, len = args.length; i < len; ++i) { | |
this[variants[v][i]] = args[i]; | |
} | |
} | |
match(cases) { | |
for (const c in cases) { | |
if (c === this[tag]) { | |
return cases[c](this); | |
} | |
} | |
} | |
toString() { | |
return `${v}(${cargs.join(', ')})`; | |
} | |
})(...args); | |
} | |
return obj; | |
}; | |
/* Example with prototype inheritance */ | |
const Maybe = data( | |
{ | |
Just: ['value'], | |
Nothing: null | |
}, | |
class { | |
bind(fn) { | |
return this.match({ | |
Just: ({ value }) => fn(value), | |
Nothing: () => this | |
}); | |
} | |
} | |
); | |
Maybe.Just(4).bind(x => Maybe.Just(x * x)); // => Some(16) | |
Maybe.None().bind(x => Maybe.Just(x)); // => None() | |
/* Example without prototype inheritance */ | |
const Option = data({ | |
Some: ['value'], | |
None: [], | |
}); | |
const bind = f => m => m.match({ | |
Some: ({ value }) => f(value), | |
None: () => m, | |
}); | |
bind(x => Option.Some(x * x))(Option.Some(4)); // => Some(16) | |
bind(x => Option.Some(x))(Option.None()); // => None() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment