Skip to content

Instantly share code, notes, and snippets.

@masaeedu
Created April 19, 2018 03:40
Show Gist options
  • Save masaeedu/5290d0bff128897a59e985f191c102a7 to your computer and use it in GitHub Desktop.
Save masaeedu/5290d0bff128897a59e985f191c102a7 to your computer and use it in GitHub Desktop.
Datatype-generic instances in JS
const GenericEither = ({ Left, Right, match }) => {
const map = f => match({ Left, Right: x => Right(f(x)) });
const of = Right;
const chain = f => match({ Left, Right: f });
return { map, of, chain };
};
// A concrete representation of an Either
const MyEither = {
Left: v => ({ left: true, v }),
Right: v => ({ left: false, v }),
match: ({ Left, Right }) => ({ left, v }) => (left ? Left(v) : Right(v))
};
// Reuse generic implementation for our Either
{
const { of, map, chain } = GenericEither(MyEither);
console.log([
map(x => x * 2)(of(21)),
map(x => x * 2)(MyEither.Left("error"))
]);
}
// A concrete representation of a Maybe
const k = Symbol("my maybe key");
const MyMaybe = {
Just: v => ({ [k]: v }),
None: {},
match: ({ Just, None }) => o => (o.hasOwnProperty(k) ? Just(o[k]) : None)
};
// Reuse generic implementation for our Maybe
{
const { None, Just } = MyMaybe;
// translating the constructor names is boilerplate
// I can easily abstract out into a single function call,
// but it's good to see the guts
const { of, map, chain } = GenericEither({
Left: None,
Right: Just,
match: ({ Left, Right }) => MyMaybe.match({ None: Left, Just: Right })
});
console.log([
map(x => x + 2)(of(42)),
map(x => x + 2)(None),
chain(x => (x > 40 ? None : of(x * 2)))(of(42)),
chain(x => (x > 40 ? None : of(x * 2)))(of(32)),
map(x => None)(of(42)),
map(x => of(x * 2))(of(42))
]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment