Typeclass mimic in JavaScript (2)
by julienrf
JavaScript
function instance(typeclasses, Type) {
function _instance(typeclass) {
Type.prototype[typeclass] = Type;
}
if (Array.isArray(typeclasses)) {
typeclasses.forEach(_instance);
} else {
_instance(typeclasses);
}
}
function inherits(Parent, Child) {
Child.prototype = Object.create(Parent.prototype);
}
function Option() {}
Option.fmap = function (f, o) {
if (o instanceof Some) {
return new Some(f(o._value));
} else {
return new None;
}
};
instance('Functor', Option);
function Some(value) {
this._value = value;
}
inherits(Option, Some);
function None() {}
inherits(Option, None);
function List(array) {
this._array = array;
}
List.pure = function (array) { return new List(array); };
List.fmap = function (f, xs) {
return new List(xs._array.map(f));
};
List.mzero = new List([]);
List.mappend = function (a, b) { return new List(a._array.concat(b._array)); };
instance(['Functor', 'Monoid'], List);
function plus1(n) { return n + 1; }
// Reusable code.
function fplus1(value) {
return value.Functor.fmap(plus1, value);
}
var o1 = new Some(42);
var o2 = new None;
var l = new List([1, 2, 3]);
console.log(fplus1(o1), fplus1(o2));
console.log(fplus1(l));
function Int(n) { this._value = n; }
Int.pure = function (n) { return new Int(n); }
Int.mzero = new Int(1);
Int.mappend = function (a, b) { return new Int(a._value * b._value); };
instance('Monoid', Int);
function Text(s) { this._value = s; }
Text.pure = function (s) { return new Text(s); }
Text.mzero = new Text('');
Text.mappend = function (a, b) { return new Text(a._value + b._value); };
instance('Monoid', Text);
function concat(xs) {
if (xs.length === 0) {
return [];
} else {
var monoid = xs[0].Monoid; // That’s beautiful.
return xs.reduce(monoid.mappend, monoid.mzero);
}
}
var ints = [1, 2, 3, 4, 5].map(Int.pure);
var texts = ['1', '2', '3', '4', '5'].map(Text.pure);
var lists = [[1, 2], [3,...