Monads/Writer monad: Difference between revisions
Content added Content deleted
m (→ES5) |
(→ES5: updated writer monad to include intermediate values in log) |
||
Line 17: | Line 17: | ||
<lang JavaScript>(function () { |
<lang JavaScript>(function () { |
||
'use strict'; |
'use strict'; |
||
// START WITH THREE SIMPLE FUNCTIONS |
// START WITH THREE SIMPLE FUNCTIONS |
||
// Square root of a number more than 0 |
// Square root of a number more than 0 |
||
function root(x) { |
function root(x) { |
||
return Math.sqrt(x); |
return Math.sqrt(x); |
||
} |
} |
||
// Add 1 |
// Add 1 |
||
function addOne(x) { |
function addOne(x) { |
||
return x + 1; |
return x + 1; |
||
} |
} |
||
// Divide by 2 |
// Divide by 2 |
||
function half(x) { |
function half(x) { |
||
return x / 2; |
return x / 2; |
||
} |
} |
||
// DERIVE LOGGING VERSIONS OF EACH FUNCTION |
// DERIVE LOGGING VERSIONS OF EACH FUNCTION |
||
function loggingVersion(f, strLog) { |
function loggingVersion(f, strLog) { |
||
return function (v) { |
return function (v) { |
||
Line 46: | Line 46: | ||
} |
} |
||
} |
} |
||
var log_root = loggingVersion(root, "obtained square root"), |
var log_root = loggingVersion(root, "obtained square root"), |
||
log_addOne = loggingVersion(addOne, "added 1"), |
log_addOne = loggingVersion(addOne, "added 1"), |
||
log_half = loggingVersion(half, "divided by 2"); |
log_half = loggingVersion(half, "divided by 2"); |
||
// UNIT/RETURN and BIND for the the WRITER MONAD |
// UNIT/RETURN and BIND for the the WRITER MONAD |
||
// The Unit / Return function for the Writer monad: |
// The Unit / Return function for the Writer monad: |
||
// 'Lifts' a raw value into the wrapped form |
// 'Lifts' a raw value into the wrapped form |
||
Line 66: | Line 66: | ||
}; |
}; |
||
} |
} |
||
// The Bind function for the Writer monad: |
// The Bind function for the Writer monad: |
||
// applies a logging version of a function |
// applies a logging version of a function |
||
// to the contents of a wrapped value |
// to the contents of a wrapped value |
||
// and return a wrapped result (with extended log) |
// and return a wrapped result (with extended log) |
||
// Writer a -> (a -> Writer b) -> Writer b |
// Writer a -> (a -> Writer b) -> Writer b |
||
function writerBind(w, f) { |
function writerBind(w, f) { |
||
var writerB = f(w.value) |
var writerB = f(w.value), |
||
v = writerB.value; |
|||
return { |
return { |
||
value: |
value: v, |
||
log: w.log + '\n' + writerB.log |
log: w.log + '\n' + writerB.log + ' -> ' + JSON.stringify(v) |
||
}; |
}; |
||
} |
} |
||
// USING UNIT AND BIND TO COMPOSE LOGGING FUNCTIONS |
// USING UNIT AND BIND TO COMPOSE LOGGING FUNCTIONS |
||
// We can compose a chain of Writer functions (of any length) with a simple foldr/reduceRight |
// We can compose a chain of Writer functions (of any length) with a simple foldr/reduceRight |
||
// which starts by 'lifting' the initial value into a Writer wrapping, |
// which starts by 'lifting' the initial value into a Writer wrapping, |
||
Line 93: | Line 94: | ||
}, writerUnit(value)); |
}, writerUnit(value)); |
||
} |
} |
||
var half_of_addOne_of_root = function (v) { |
var half_of_addOne_of_root = function (v) { |
||
return logCompose( |
return logCompose( |
||
Line 99: | Line 100: | ||
); |
); |
||
}; |
}; |
||
return half_of_addOne_of_root(5); |
return half_of_addOne_of_root(5); |
||
})();</lang> |
})();</lang> |
||
Line 105: | Line 106: | ||
{{Out}} |
{{Out}} |
||
<pre>{ |
|||
<pre>{"value":1.618033988749895, "log":"Initial value: 5\nobtained square root\nadded 1\ndivided by 2"}</pre> |
|||
"value":1.618033988749895, |
|||
"log":"Initial value: 5\n |
|||
obtained square root -> 2.23606797749979\n |
|||
added 1 -> 3.23606797749979\n |
|||
divided by 2 -> 1.618033988749895" |
|||
}</pre> |