Skip to content

Instantly share code, notes, and snippets.

@eddmann
Created March 28, 2015 13:36
Show Gist options
  • Save eddmann/6d18aa8a50eb5f64e9ed to your computer and use it in GitHub Desktop.
Save eddmann/6d18aa8a50eb5f64e9ed to your computer and use it in GitHub Desktop.
JS Bin // source http://jsbin.com/vosiye
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<script id="jsbin-javascript">
"use strict";
var _toArray = function (arr) { return Array.isArray(arr) ? arr : Array.from(arr); };
var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; };
var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); };
console.clear();
var log = function (x) {
return console.log(x ? x.toString() : x);
};
var curry = function (fn) {
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
var _curry = function (args) {
return args.length < fn.length ? function () {
for (var _len2 = arguments.length, _args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
_args[_key2] = arguments[_key2];
}
return _curry([].concat(_toArray(args), _toArray(_args)));
} : fn.apply(undefined, _toArray(args));
};
return _curry(args);
};
var compose = function () {
for (var _len = arguments.length, fns = Array(_len), _key = 0; _key < _len; _key++) {
fns[_key] = arguments[_key];
}
return fns.reduce(function (f, g) {
return function () {
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
return f(g.apply(undefined, _toArray(args)));
};
});
};
var fmap = curry(function (fn, functor) {
return functor.fmap(fn);
}),
bind = curry(function (fn, monad) {
return monad.bind(fn);
}),
mjoin = function (monad) {
return monad.bind(function (x) {
return x;
});
};
var Maybe = (function () {
var Some = function (x) {
this.x = x;
};
Some.prototype.fmap = function (fn) {
return Maybe.of(fn(this.x));
};
Some.prototype.bind = function (fn) {
return fn(this.x);
};
Some.prototype.toString = function () {
return "Some(" + this.x + ")";
};
var None = function () {};
None.prototype.fmap = function (fn) {
return new None();
};
None.prototype.bind = function (fn) {
return new None();
};
None.prototype.toString = function () {
return "None";
};
var isNull = function (x) {
return x === null || x === undefined;
};
return {
of: function (x) {
return isNull(x) ? new None() : new Some(x);
},
lift: function (fn) {
return function () {
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return Maybe.of(fn.apply(undefined, _toArray(args)));
};
},
Some: Some,
None: None
};
})();
var isNum = function (x) {
return !isNaN(parseFloat(x)) && isFinite(x);
},
add = function (a, b) {
return isNum(a) && isNum(b) ? a + b : null;
},
madd = Maybe.lift(add);
log(add(1, 2)); // 3
log(add(1, null)); // null
log(madd(1, 2)); // Some(3)
log(madd(1, null)); // None
var get = curry(function (prop, obj) {
return obj[prop];
}),
mget = function (prop) {
return Maybe.lift(get(prop));
};
var joe = {
name: "Joe Bloggs",
age: 25,
address: {
street: "Cinder Drive"
}
};
var sally = {
name: "Sally Ann" };
log(get("age")(sally)); // undefined
log(mget("age")(sally)); // None
log(mget("age")(joe)); // Some(25)
var getAddressFmap = compose(fmap(mget("street")), mget("address")),
getAddressJoin = compose(mjoin, getAddressFmap),
getAddressBind = compose(mjoin, fmap(mget("street")), mget("address"));
log(getAddressFmap(joe)); // Some(Some(Cinder Drive))
log(getAddressJoin(joe)); // Some(Cinder Drive)
log(getAddressBind(joe)); // Some(Cinder Drive)
var Maybe = (function () {
function Maybe() {}
_prototypeProperties(Maybe, {
of: {
value: function of(x) {
var isNull = x === undefined || x === null;
return isNull ? new None() : new Some(x);
},
writable: true,
enumerable: true,
configurable: true
},
lift: {
value: function lift(fn) {
return function () {
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return Maybe.of(fn.apply(undefined, _toArray(args)));
};
},
writable: true,
enumerable: true,
configurable: true
}
}, {
of: {
value: function of(x) {
return Maybe.of(x);
},
writable: true,
enumerable: true,
configurable: true
}
});
return Maybe;
})();
var None = (function (Maybe) {
function None() {
if (Object.getPrototypeOf(None) !== null) {
Object.getPrototypeOf(None).apply(this, arguments);
}
}
_inherits(None, Maybe);
_prototypeProperties(None, null, {
fmap: {
value: function fmap(fn) {
return this;
},
writable: true,
enumerable: true,
configurable: true
},
bind: {
value: function bind(fn) {
return this;
},
writable: true,
enumerable: true,
configurable: true
},
toString: {
value: function toString() {
return "None";
},
writable: true,
enumerable: true,
configurable: true
}
});
return None;
})(Maybe);
var Some = (function (Maybe) {
function Some(x) {
this.x = x;
}
_inherits(Some, Maybe);
_prototypeProperties(Some, null, {
fmap: {
value: function fmap(fn) {
return this.of(fn(this.x));
},
writable: true,
enumerable: true,
configurable: true
},
bind: {
value: function bind(fn) {
return fn.call(this, this.x);
},
writable: true,
enumerable: true,
configurable: true
},
toString: {
value: function toString() {
return "Some(" + this.x + ")";
},
writable: true,
enumerable: true,
configurable: true
}
});
return Some;
})(Maybe);
var doM = function (exp) {
var tokenize = function (exp) {
return exp.toString().split(/[\n;]/).slice(1, -1).map(function (s) {
return s.trim();
}).filter(Boolean);
};
var evaluate = function (tokens) {
if (tokens.length === 0) return "";
var token = tokens.shift(),
match = undefined;
if (match = token.match(/^return (.+)$/)) return "return this.of(" + match[1] + ");" + evaluate(tokens);
if (match = token.match(/^(.+) <= (.+)$/)) return "return " + match[2] + ".bind(function(" + match[1] + ") { " + evaluate(tokens) + " });";
return evaluate(tokens);
};
return compose(Function, evaluate, tokenize)(exp)();
};
var street = doM(function () {
address <= mget("address")(joe);
street <= mget("street")(address);
return street;
});
log(street);
</script>
<script id="jsbin-source-javascript" type="text/javascript">"use strict"
console.clear();
let log = (x) => console.log(x ? x.toString() : x);
let curry = (fn, ...args) => {
let _curry = (args) =>
args.length < fn.length
? (..._args) => _curry([...args, ..._args])
: fn(...args);
return _curry(args);
};
let compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)));
let fmap = curry((fn, functor) => functor.fmap(fn)),
bind = curry((fn, monad) => monad.bind(fn)),
mjoin = (monad) => monad.bind((x) => x);
let Maybe = (function () {
let Some = function (x) { this.x = x; };
Some.prototype.fmap = function (fn) { return Maybe.of(fn(this.x)); };
Some.prototype.bind = function (fn) { return fn(this.x); };
Some.prototype.toString = function () { return `Some(${this.x})`; };
let None = function () {};
None.prototype.fmap = (fn) => new None;
None.prototype.bind = (fn) => new None;
None.prototype.toString = () => 'None';
let isNull = (x) => x === null || x === undefined;
return {
of: (x) => isNull(x) ? new None : new Some(x),
lift: (fn) => (...args) => Maybe.of(fn(...args)),
Some,
None
};
})();
let isNum = (x) => !isNaN(parseFloat(x)) && isFinite(x),
add = (a, b) => isNum(a) && isNum(b) ? a + b : null,
madd = Maybe.lift(add);
log(add(1, 2)); // 3
log(add(1, null)); // null
log(madd(1, 2)); // Some(3)
log(madd(1, null)); // None
let get = curry((prop, obj) => obj[prop]),
mget = (prop) => Maybe.lift(get(prop));
let joe = {
name: 'Joe Bloggs',
age: 25,
address: {
street: 'Cinder Drive'
}
};
let sally = {
name: 'Sally Ann',
};
log(get('age')(sally)); // undefined
log(mget('age')(sally)); // None
log(mget('age')(joe)); // Some(25)
let getAddressFmap = compose(fmap(mget('street')), mget('address')),
getAddressJoin = compose(mjoin, getAddressFmap),
getAddressBind = compose(mjoin, fmap(mget('street')), mget('address'));
log(getAddressFmap(joe)); // Some(Some(Cinder Drive))
log(getAddressJoin(joe)); // Some(Cinder Drive)
log(getAddressBind(joe)); // Some(Cinder Drive)
class Maybe {
static of(x) {
let isNull = x === undefined || x === null;
return isNull ? new None : new Some(x);
}
of(x) { return Maybe.of(x); }
static lift(fn) { return (...args) => Maybe.of(fn(...args)); }
}
class None extends Maybe {
fmap(fn) { return this; }
bind(fn) { return this; }
toString() { return 'None'; }
}
class Some extends Maybe {
constructor(x) { this.x = x; }
fmap(fn) { return this.of(fn(this.x)); }
bind(fn) { return fn.call(this, this.x); }
toString() { return `Some(${this.x})`; }
}
let doM = function(exp) {
let tokenize = (exp) => {
return exp
.toString()
.split(/[\n;]/)
.slice(1, -1)
.map((s) => s.trim())
.filter(Boolean);
};
let evaluate = (tokens) => {
if (tokens.length === 0) return '';
let token = tokens.shift(), match;
if (match = token.match(/^return (.+)$/))
return `return this.of(${match[1]});` + evaluate(tokens);
if (match = token.match(/^(.+) <= (.+)$/))
return `return ${match[2]}.bind(function(${match[1]}) { ${evaluate(tokens)} });`;
return evaluate(tokens);
};
return compose(Function, evaluate, tokenize)(exp)();
};
let street = doM(() => {
address <= mget('address')(joe)
street <= mget('street')(address)
return street
});
log(street);
</script></body>
</html>
"use strict";
var _toArray = function (arr) { return Array.isArray(arr) ? arr : Array.from(arr); };
var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; };
var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); };
console.clear();
var log = function (x) {
return console.log(x ? x.toString() : x);
};
var curry = function (fn) {
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
var _curry = function (args) {
return args.length < fn.length ? function () {
for (var _len2 = arguments.length, _args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
_args[_key2] = arguments[_key2];
}
return _curry([].concat(_toArray(args), _toArray(_args)));
} : fn.apply(undefined, _toArray(args));
};
return _curry(args);
};
var compose = function () {
for (var _len = arguments.length, fns = Array(_len), _key = 0; _key < _len; _key++) {
fns[_key] = arguments[_key];
}
return fns.reduce(function (f, g) {
return function () {
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
return f(g.apply(undefined, _toArray(args)));
};
});
};
var fmap = curry(function (fn, functor) {
return functor.fmap(fn);
}),
bind = curry(function (fn, monad) {
return monad.bind(fn);
}),
mjoin = function (monad) {
return monad.bind(function (x) {
return x;
});
};
var Maybe = (function () {
var Some = function (x) {
this.x = x;
};
Some.prototype.fmap = function (fn) {
return Maybe.of(fn(this.x));
};
Some.prototype.bind = function (fn) {
return fn(this.x);
};
Some.prototype.toString = function () {
return "Some(" + this.x + ")";
};
var None = function () {};
None.prototype.fmap = function (fn) {
return new None();
};
None.prototype.bind = function (fn) {
return new None();
};
None.prototype.toString = function () {
return "None";
};
var isNull = function (x) {
return x === null || x === undefined;
};
return {
of: function (x) {
return isNull(x) ? new None() : new Some(x);
},
lift: function (fn) {
return function () {
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return Maybe.of(fn.apply(undefined, _toArray(args)));
};
},
Some: Some,
None: None
};
})();
var isNum = function (x) {
return !isNaN(parseFloat(x)) && isFinite(x);
},
add = function (a, b) {
return isNum(a) && isNum(b) ? a + b : null;
},
madd = Maybe.lift(add);
log(add(1, 2)); // 3
log(add(1, null)); // null
log(madd(1, 2)); // Some(3)
log(madd(1, null)); // None
var get = curry(function (prop, obj) {
return obj[prop];
}),
mget = function (prop) {
return Maybe.lift(get(prop));
};
var joe = {
name: "Joe Bloggs",
age: 25,
address: {
street: "Cinder Drive"
}
};
var sally = {
name: "Sally Ann" };
log(get("age")(sally)); // undefined
log(mget("age")(sally)); // None
log(mget("age")(joe)); // Some(25)
var getAddressFmap = compose(fmap(mget("street")), mget("address")),
getAddressJoin = compose(mjoin, getAddressFmap),
getAddressBind = compose(mjoin, fmap(mget("street")), mget("address"));
log(getAddressFmap(joe)); // Some(Some(Cinder Drive))
log(getAddressJoin(joe)); // Some(Cinder Drive)
log(getAddressBind(joe)); // Some(Cinder Drive)
var Maybe = (function () {
function Maybe() {}
_prototypeProperties(Maybe, {
of: {
value: function of(x) {
var isNull = x === undefined || x === null;
return isNull ? new None() : new Some(x);
},
writable: true,
enumerable: true,
configurable: true
},
lift: {
value: function lift(fn) {
return function () {
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return Maybe.of(fn.apply(undefined, _toArray(args)));
};
},
writable: true,
enumerable: true,
configurable: true
}
}, {
of: {
value: function of(x) {
return Maybe.of(x);
},
writable: true,
enumerable: true,
configurable: true
}
});
return Maybe;
})();
var None = (function (Maybe) {
function None() {
if (Object.getPrototypeOf(None) !== null) {
Object.getPrototypeOf(None).apply(this, arguments);
}
}
_inherits(None, Maybe);
_prototypeProperties(None, null, {
fmap: {
value: function fmap(fn) {
return this;
},
writable: true,
enumerable: true,
configurable: true
},
bind: {
value: function bind(fn) {
return this;
},
writable: true,
enumerable: true,
configurable: true
},
toString: {
value: function toString() {
return "None";
},
writable: true,
enumerable: true,
configurable: true
}
});
return None;
})(Maybe);
var Some = (function (Maybe) {
function Some(x) {
this.x = x;
}
_inherits(Some, Maybe);
_prototypeProperties(Some, null, {
fmap: {
value: function fmap(fn) {
return this.of(fn(this.x));
},
writable: true,
enumerable: true,
configurable: true
},
bind: {
value: function bind(fn) {
return fn.call(this, this.x);
},
writable: true,
enumerable: true,
configurable: true
},
toString: {
value: function toString() {
return "Some(" + this.x + ")";
},
writable: true,
enumerable: true,
configurable: true
}
});
return Some;
})(Maybe);
var doM = function (exp) {
var tokenize = function (exp) {
return exp.toString().split(/[\n;]/).slice(1, -1).map(function (s) {
return s.trim();
}).filter(Boolean);
};
var evaluate = function (tokens) {
if (tokens.length === 0) return "";
var token = tokens.shift(),
match = undefined;
if (match = token.match(/^return (.+)$/)) return "return this.of(" + match[1] + ");" + evaluate(tokens);
if (match = token.match(/^(.+) <= (.+)$/)) return "return " + match[2] + ".bind(function(" + match[1] + ") { " + evaluate(tokens) + " });";
return evaluate(tokens);
};
return compose(Function, evaluate, tokenize)(exp)();
};
var street = doM(function () {
address <= mget("address")(joe);
street <= mget("street")(address);
return street;
});
log(street);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment