Skip to content

Instantly share code, notes, and snippets.

@fabioyamate
Created May 21, 2014 21:29
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fabioyamate/7074ebceb143f551a70e to your computer and use it in GitHub Desktop.
Save fabioyamate/7074ebceb143f551a70e to your computer and use it in GitHub Desktop.
Playground for a monad maybe implementation in Javascript
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>jQuery Snippet</title>
</head>
<body>
<div id="container"></div>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.5.2/underscore-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore-contrib/0.1.4/underscore-contrib.min.js"></script>
<script>
function Just(value) {
return {
value: value,
bind: function(f) {
return f(this.value);
},
unit: Just
};
}
function Nothing() { return Nothing; }
Nothing.bind = function() {
return Nothing;
}
// liftM :: Monad m => (a1 -> r) -> m a1 -> m r
function liftM(f, m) {
return m.bind(function(i) {
return m.unit(f(i));
});
}
// liftM2 :: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
function liftM2(f, m1, m2) {
return m1.bind(function(i) {
return m2.bind(function(j) {
return m1.unit(f(i, j));
});
});
}
// liftM3 :: Monad m => (a1 -> a2 -> a3 -> r) -> m a1 -> m a2 -> m a3 -> m r
function liftM3(f, m1, m2, m3) {
return m1.bind(function(i) {
return m2.bind(function(j) {
return m3.bind(function(k) {
return m1.unit(f(i, j, k));
});
});
});
}
var phonebook = 1;
var governamentalDatabase = 2;
var taxDatabase = 3;
// lookup :: String -> ... -> Maybe
function lookup(name, database) {
if (database == 1) {
console.log('1');
return Nothing;
} else if (database == 2) {
console.log('2');
return Just('registration');
} else if (database == 3) {
console.log('3');
return Just('number');
}
}
function getTaxOwed(name) {
return lookup(name, phonebook).bind(function(number) {
return lookup(number, governamentalDatabase).bind(function(registration) {
return lookup(registration, taxDatabase);
});
});
}
// getTaxOwed :: String -> Maybe
// do
// number <- lookup(name, phonebook)
// registration <- lookup(number, go...)
// lookup(registration, taxDatab)
// => Just(tax)
// lookup(name, phonebook) >>= \number
// -> lookup(number, gover) >>= \registration
// -> lookup(registration, taxDatabase)
// do
// x <-Just(3)
// y <- Just(4)
// return $ x + y
console.log(getTaxOwed('fabio'));
function sum(a, b) {
return a + b;
}
console.log(liftM2(sum, Just(3), Nothing));
function Try(expr) {
try {
return Success(expr);
} catch(e) {
return Failure(e);
}
}
function Success(expr) {
var value = expr();
return {
bind: function(f) {
try {
return f(value);
} catch (e) {
return Failure(e);
}
}
};
}
function Failure(exception) {
return {
bind: function() {
return exception;
}
};
}
parseNumber = function(v) {
var value = parseInt(v, 10);
if (value === NaN) {
throw 'a';
} else {
return value;
}
}
var a = Try(function() { return parseNumber("1") }).bind(function(a) {
return Try(function() { return parseNumber("2") }).bind(function(b) {
return Try(a + b);
});
});
console.log(a);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment