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,...