Skip to content

Instantly share code, notes, and snippets.

@kazu69
Last active October 10, 2015 01:00
Show Gist options
  • Save kazu69/96344bf338061ca75552 to your computer and use it in GitHub Desktop.
Save kazu69/96344bf338061ca75552 to your computer and use it in GitHub Desktop.
Haskell like monad in ES6
var UpperCase = value => {
if(!value) return value;
return value.toUpperCase();
}
var LowerCase = value => {
if(!value) return value;
return value.toLowerCase();
}
// Identity monad
Monad.create(
Monad.create('hello').bind(UpperCase)
).bind(LowerCase) // => hello
let list = ['a','b'];
var beforeAdd = (obj, array) => {
var result = [];
if(!(obj instanceof Array)) obj = [obj];
obj.forEach(function(item) {
var tmp = array.map(function(words) {
return words + '-' + item;
});
result = result.concat(tmp);
});
return result;
}
var afterAdd = (obj, array) => {
var result = [];
if(!(obj instanceof Array)) obj = [obj];
obj.forEach(function(item) {
var tmp = array.map(function(words) {
return item + '-' + words;
});
result = result.concat(tmp);
});
return result;
}
// List
Monad.create(
Monad.create('test').bind(beforeAdd, [list])
).bind(afterAdd, [list]); // => [ 'a-test-a', 'a-test-b', 'b-test-a', 'b-test-b' ]
var UpperCase = value => {
if(!value) return value;
return value.toUpperCase();
}
var LowerCase = value => {
if(!value) return value;
return value.toLowerCase();
}
// Maybe
Monad.create(
Monad.create(null).bind(UpperCase)
).bind(LowerCase); // => null
'use strict';
class Monad {
constructor(value) {
if (typeof modifier === 'function') {
this._modifier = value;
} else {
this._value = value;
}
}
static create(func) {
return new Monad(func);
}
value() {
if(this._value === undefined) return undefined;
return this._value;
}
bind(func, args) {
return func.apply(undefined, [this.value()].concat(Array.prototype.slice.apply(args || [])));
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>QUnit Example</title>
<link rel="stylesheet" href="https://code.jquery.com/qunit/qunit-1.19.0.css">
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script src="https://code.jquery.com/qunit/qunit-1.19.0.js"></script>
<script src="es6.js"></script>
<script src="test.js"></script>
</body>
</html>
QUnit.test( '`return x >>= f` should be equal `f a`', function( assert ) {
var f = function(a) { return a * 2; }
var left = Monad.create(1).bind(f);
var right = f(1);
assert.equal(left, right, 'left, right is equal');
});
QUnit.test('`m >>= return` should be equal `m`', function( assert ) {
var left = Monad.create(Monad.create().value());
var right = Monad.create();
assert.deepEqual(left, right, 'left, right is equal');
});
QUnit.test('`(m >>= f) >>= g` should be equal `m >>= (x -> f x >>= g`', function( assert ) {
var f = function f(num) {
return num + 1;
}
var g = function(num) {
return num * 2;
}
var left = Monad.create( Monad.create(1).bind(f) ).bind(g);
var right = Monad.create( Monad.create(f(1)).bind(g) ).value();
assert.deepEqual(left, right, 'left, right is equal');
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment