Last active
May 24, 2021 02:31
-
-
Save DrBoolean/917f9a34fd87716a455493c96a868633 to your computer and use it in GitHub Desktop.
Tail of three envs
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
const compose = (f, g) => x => f(g(x)) | |
const Id = x => | |
({ | |
fold: f => f(x), | |
map: f => Id(f(x)) | |
}) | |
Id.of = Id | |
const Tuple = (_1, _2) => | |
({ | |
_1, | |
_2, | |
map: f => Tuple(_1, f(_2)), | |
extend: f => Tuple(_1, f(Tuple(_1, _2))), | |
extract: () => _2 | |
}) | |
Tuple.of = x => Tuple(x, x) | |
const Fn = run => | |
({ | |
run, | |
map: f => Fn(x => f(run(x))), | |
chain: f => Fn(x => f(run(x)).run(x)) | |
}) | |
Fn.of = x => Fn(() => x) | |
const objToString = style => | |
Object.keys(style) | |
.reduce((acc, key) => | |
acc.concat(`${key}: ${style[key]}`), '') // this is foldMap | |
const Html = { | |
div: content => | |
({tag: 'div', content, style:{}}), | |
setStyle: (el, style) => | |
Object.assign({}, el, {style}), | |
render: (el, style) => | |
`<${el.tag} style=${objToString(el.style)}>${el.content}</${el.tag}>`, | |
} | |
// EXAMPLE 1 | |
//============== | |
// Toss it in a closure. | |
// Benefits: | |
// Easy to implement | |
// Drawbacks: | |
// Everything has access to settings everywhere whether it needs it or not. | |
// Implicitly stateful | |
// Need data up front | |
const ClosureExample = settings => { | |
const createPage = content => | |
Id.of(content) | |
.map(Html.div) | |
.map(div => | |
Html.setStyle(div, {'background-color': settings.favoriteColor}) | |
) | |
.fold(Html.render) | |
const getContent = id => | |
({ | |
1: 'hi i am some content', | |
2: 'i am more content' | |
})[id] | |
const blog = compose(createPage, getContent) | |
return blog | |
} | |
// EXAMPLE 2 | |
//============== | |
// Use Fn monad (called Reader) | |
// Benefits: | |
// Things which need access to the environment (Fn) are explicit | |
// Things which don't need access, don't have access | |
// Lazy access so you can pass the stuff in later. | |
// Implements standard monadic interface | |
// Drawbacks: | |
// Bit tricky to understand at first | |
const ReaderExample = () => { | |
const createPage = content => | |
Fn.of(content) | |
.map(Html.div) | |
.chain(div => | |
Fn(settings => | |
Html.setStyle(div, {'background-color': settings.favoriteColor}) | |
) | |
) | |
.map(Html.render) | |
const getContent = id => | |
({ | |
1: 'hi i am some content', | |
2: 'i am more content' | |
})[id] | |
const blog = id => | |
Fn.of(id) | |
.map(getContent) | |
.chain(createPage) | |
return blog | |
} | |
// EXAMPLE 3 | |
//============== | |
// Use Tuple comonad (called env) | |
// Benefits: | |
// Things which need access to the environment (Fn) are explicit | |
// Things which don't need access, don't have access | |
// Implements standard comonadic interface | |
// Drawbacks: | |
// Tricky to understand at first | |
// Need data up front | |
const TupleExample = () => { | |
const createPage = tuple => | |
tuple | |
.map(Html.div) | |
.extend(({_1: settings, _2: div}) => | |
Html.setStyle(div, {'background-color': settings.favoriteColor}) | |
) | |
.map(Html.render) | |
.extract() | |
const getContent = id => | |
({ | |
1: 'hi i am some content', | |
2: 'i am more content' | |
})[id] | |
const blog = tuple => | |
tuple.map(getContent) | |
.extend(createPage) | |
.extract() | |
return blog | |
} | |
const settings = {favoriteColor: 'green'} | |
const closureExample = ClosureExample(settings) | |
const readerExample = ReaderExample() | |
const tupleExample = TupleExample() | |
console.log('closure', closureExample(1)) | |
console.log('reader', readerExample(1).run(settings)) | |
console.log('tuple', tupleExample(Tuple(settings, 1))) | |
//closure <div style=background-color: green>hi i am some content</div> | |
//reader <div style=background-color: green>hi i am some content</div> | |
//tuple <div style=background-color: green>hi i am some content</div> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment