Skip to content

Instantly share code, notes, and snippets.

@buzzdecafe
Forked from CrossEye/Functor.js
Last active October 18, 2023 07:28
Show Gist options
  • Save buzzdecafe/5721205 to your computer and use it in GitHub Desktop.
Save buzzdecafe/5721205 to your computer and use it in GitHub Desktop.
var curry = function(fn) {
var arity = fn.length;
var f = function(args) {
return function () {
var newArgs = (args || []).concat([].slice.call(arguments, 0));
if (newArgs.length >= arity) {
return fn.apply(this, newArgs);
}
else {return f(newArgs);}
};
};
return f([]);
};
var compose = function(f, g) {
return function() {
return f.call(this, (g.apply(this, arguments)));
};
};
var Maybe = function Maybe(val) {
if (!(this instanceof Maybe)) {return new Maybe(val);}
this.val = val;
};
var Either = function Either(left, right) {
if (!(this instanceof Either)) {return new Either(left, right);}
this.left = left;
this.right = right;
};
(function(global) {
global.Functor = function(conf) {
Functor.types[conf.key] = {
obj: conf.obj,
fmap: conf.fmap
};
};
Functor.types = {};
global.fmap = curry(function(f, obj) {
var key = obj.constructor.name; // or even nastier: obj.constructor.toString().match(/function (\w*)/)[1]
return Functor.types[key].fmap(f, obj);
});
}(this));
// relies on NFEs to lookup correct fmap. not great.
Functor({key: "Array", obj: Array, fmap: function(f, arr){
return arr.map(function(x){return f(x);});
}});
Functor({key: "Function", obj: Function, fmap: function(f, g) {
return compose(f, g);
}});
Functor({key: "Maybe", obj: Maybe, fmap: function(f, maybe) {
return (maybe.val == null) ? maybe : Maybe(f(maybe.val));
}});
Functor({key: "Either", obj: Either, fmap: function(f, either) {
return (either.right == null) ? Either(f(either.left), null) : Either(either.left, f(either.right));
}});
var plus1 = function(n) {return n + 1;};
var times2 = function(n) {return n * 2;};
console.log(fmap(plus1, [2, 4, 6, 8])); //=> [3, 5, 7, 9]
console.log(fmap(plus1, Maybe(5))); //=> Maybe(6)
console.log(fmap(plus1, Maybe(null))); //=> Maybe(null)
console.log(fmap(plus1, times2)(3)); //=> 7 (= 3 * 2 + 1)
console.log(fmap(plus1, Either(10, 20))); //=> Either(10, 21)
console.log(fmap(plus1, Either(10, null))); //=> Either(11, null)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment