Skip to content

Instantly share code, notes, and snippets.

@CrossEye
Last active July 26, 2020 19:59

Revisions

  1. CrossEye revised this gist Jun 15, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Functor.js
    Original file line number Diff line number Diff line change
    @@ -3,7 +3,7 @@
    throw new TypeError("fmap called on unregistered type: " + obj);
    };

    // inefficient as hell, but as long as there aren't too many types...
    // inefficient as hell, but as long as there aren't too many types....
    global.Functor = function(type, defs) {
    var oldTypes = types;
    types = function(obj) {
  2. CrossEye revised this gist Jun 5, 2013. 1 changed file with 16 additions and 23 deletions.
    39 changes: 16 additions & 23 deletions usage.js
    Original file line number Diff line number Diff line change
    @@ -1,36 +1,29 @@
    // These need to be registered from general to specific.
    // The alternative I can see is to use a prototype-based solutions as done in:
    // https://github.com/loop-recur/typeclasses/blob/master/functor.js
    Functor(Array, {
    fmap: function(f, arr){
    return arr.map(function(x){
    return f(x);
    });
    }
    });

    Functor(Function, {
    fmap: function(f, g){ return compose(f, g); }
    });

    Functor(Maybe, {
    fmap: function(f, maybe) {
    return (maybe.val == null) ? maybe : Maybe(f(maybe.val));
    }
    });

    Functor(Either, {
    fmap: function(f, either) {
    return (either.right == null) ? Either(f(either.left), null) : Either(either.left, f(either.right));
    }
    });
    Functor(Array, {fmap: function(f, arr){
    return arr.map(function(x){return f(x);});
    }});
    Functor(Function, {fmap: function(f, g) {
    return compose(f, g);
    }});

    Functor(Maybe, {fmap: function(f, maybe) {
    return (maybe.val == null) ? maybe : Maybe(f(maybe.val));
    }});

    Functor(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, 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)
  3. CrossEye revised this gist Jun 5, 2013. 1 changed file with 3 additions and 0 deletions.
    3 changes: 3 additions & 0 deletions usage.js
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,6 @@
    // These need to be registered from general to specific.
    // The alternative I can see is to use a prototype-based solutions as done in:
    // https://github.com/loop-recur/typeclasses/blob/master/functor.js
    Functor(Array, {
    fmap: function(f, arr){
    return arr.map(function(x){
  4. CrossEye revised this gist Jun 5, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Functor.js
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,6 @@
    (function(global) {
    var types = function(obj) {
    throw new TypeError("fmap called on unknown type: " + obj);
    throw new TypeError("fmap called on unregistered type: " + obj);
    };

    // inefficient as hell, but as long as there aren't too many types...
  5. CrossEye revised this gist Jun 5, 2013. 1 changed file with 6 additions and 8 deletions.
    14 changes: 6 additions & 8 deletions Functor.js
    Original file line number Diff line number Diff line change
    @@ -1,22 +1,20 @@
    (function(global) {

    var types = function(f, obj) {
    var types = function(obj) {
    throw new TypeError("fmap called on unknown type: " + obj);
    };

    // inefficient as hell, but as long as there aren't too many types...
    global.Functor = function(type, defs) {
    var oldTypes = types;
    types = function(f, obj) {
    types = function(obj) {
    if (type.prototype.isPrototypeOf(obj)) {
    return defs.fmap(f, obj);
    return defs;
    }
    return oldTypes(f, obj);
    return oldTypes(obj);
    }
    };

    global.fmap = curry(function(f, obj) {
    return types(f, obj);
    return types(obj).fmap(f, obj);
    });

    }(this));
    }(this));
  6. CrossEye revised this gist Jun 5, 2013. 1 changed file with 6 additions and 6 deletions.
    12 changes: 6 additions & 6 deletions usage.js
    Original file line number Diff line number Diff line change
    @@ -16,6 +16,12 @@ Functor(Maybe, {
    }
    });

    Functor(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;};

    @@ -25,9 +31,3 @@ 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)

    Functor(Either, {
    fmap: function(f, either) {
    return (either.right == null) ? Either(f(either.left), null) : Either(either.left, f(either.right));
    }
    });
  7. CrossEye revised this gist Jun 5, 2013. 2 changed files with 10 additions and 10 deletions.
    10 changes: 0 additions & 10 deletions examples.js
    Original file line number Diff line number Diff line change
    @@ -1,10 +0,0 @@
    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)

    10 changes: 10 additions & 0 deletions usage.js
    Original file line number Diff line number Diff line change
    @@ -16,6 +16,16 @@ Functor(Maybe, {
    }
    });

    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)

    Functor(Either, {
    fmap: function(f, either) {
    return (either.right == null) ? Either(f(either.left), null) : Either(either.left, f(either.right));
  8. CrossEye created this gist Jun 5, 2013.
    22 changes: 22 additions & 0 deletions Functor.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,22 @@
    (function(global) {

    var types = function(f, obj) {
    throw new TypeError("fmap called on unknown type: " + obj);
    };

    // inefficient as hell, but as long as there aren't too many types...
    global.Functor = function(type, defs) {
    var oldTypes = types;
    types = function(f, obj) {
    if (type.prototype.isPrototypeOf(obj)) {
    return defs.fmap(f, obj);
    }
    return oldTypes(f, obj);
    }
    };

    global.fmap = curry(function(f, obj) {
    return types(f, obj);
    });

    }(this));
    31 changes: 31 additions & 0 deletions dependencies.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,31 @@
    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(val) {
    if (!(this instanceof Maybe)) {return new Maybe(val);}
    this.val = val;
    };

    var Either = function(left, right) {
    if (!(this instanceof Either)) {return new Either(left, right);}
    this.left = left;
    this.right = right;
    };
    10 changes: 10 additions & 0 deletions examples.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,10 @@
    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)

    23 changes: 23 additions & 0 deletions usage.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,23 @@
    Functor(Array, {
    fmap: function(f, arr){
    return arr.map(function(x){
    return f(x);
    });
    }
    });

    Functor(Function, {
    fmap: function(f, g){ return compose(f, g); }
    });

    Functor(Maybe, {
    fmap: function(f, maybe) {
    return (maybe.val == null) ? maybe : Maybe(f(maybe.val));
    }
    });

    Functor(Either, {
    fmap: function(f, either) {
    return (either.right == null) ? Either(f(either.left), null) : Either(either.left, f(either.right));
    }
    });