Last active
July 6, 2017 10:00
-
-
Save towry/a2205dfd7c04b85e2963fff209bd3b61 to your computer and use it in GitHub Desktop.
explain monad in js.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*! | |
https://blog.jcoglan.com/2011/03/05/translation-from-haskell-to-javascript-of-selected-portions-of-the-best-introduction-to-monads-ive-ever-read/ | |
this is a function with side effect, to dealing with side effect, | |
we can format it into return value, because pure function can only | |
have input and output (return) effect to outside world. | |
```js | |
// signature: x -> y | |
var sin = function (x) { | |
console.log('called from sin'); | |
return Math.sin(x); | |
} | |
// signature: x -> (y, y) | |
var sinPure = function (x) { | |
return [Math.sin(x), 'called from sin']; | |
} | |
``` | |
So here the second value in container is string `'called from sin'`, | |
we can think it as side effect. If we are performing IO task in such | |
function, we can wrap the IO result into the return value. | |
*/ | |
// with side effect | |
var sin = function (x) { | |
return [Math.sin(x), "called from sin"]; | |
} | |
var cube = function (x) { | |
return [x * x * x, "called from cube"]; | |
} | |
// make one's return value as argument to another. | |
var compose = function (f, g) { | |
return function (x) { | |
return f(g(x)); | |
} | |
} | |
// make sure a functions take a tuple and return a tuple. | |
var bind = function (f) { | |
return function (x) { | |
var a = x[0]; | |
var b = x[1]; | |
var c = f(a); | |
var y = c[0]; | |
var w = c[1]; | |
return [y, b + ' ' + w]; | |
} | |
} | |
// for dealing with side effect. | |
// we can think the second value in container([x, '']) is a side effect, | |
// because sin and cube function has side effects, and we need to chain | |
// with such functions, so we have a monad that simulate sin and cube function. | |
// this function just accept one value and wrap it in a container. | |
var unit = function (x) { | |
return [x, ''] | |
} | |
var lift = function (f) { | |
return function (x) { | |
return unit(f(x)) | |
} | |
} | |
var input = 3; | |
// bind, unit | |
// var value = cube(sin(input)); | |
// x -> y | |
var round = function (x) { return Math.round(x) } | |
// x -> (y, y) | |
// make it like sin function, so we can chain it together. | |
var roundLifted = lift(round); | |
// make args and return value symemetric. | |
// (x, x) -> (y, y) | |
var roundBinded = bind(roundLifted); | |
// compose sin and cube | |
var sinAndCube = compose(bind(cube), bind(sin)); | |
// then compose with round. | |
var sinAndCubeAndRound = compose(sinAndCube, roundBinded); | |
var value = sinAndCubeAndRound(unit(input)); | |
console.log(value); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment