Skip to content

Instantly share code, notes, and snippets.

@i-am-tom
Last active January 13, 2024 01:35
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save i-am-tom/55cf31f0afab5808951c3d2e67e6fc65 to your computer and use it in GitHub Desktop.
Save i-am-tom/55cf31f0afab5808951c3d2e67e6fc65 to your computer and use it in GitHub Desktop.
A Fantasy Land-compliant type for lazy computation.
// Some lazily-evaluated thunk.
const thunk = Lazy[fl.of](2)[fl.map](x => 'My number is ' + x)
[fl.map](console.log.bind(console))
// No console log...
// ... until we `run` the laziness:
thunk.run() // Logs "My number is 2"
// * You can also build infinite lists! * //
// Create an infinite list froma given start
const countUp = head => ({
head,
tail: Lazy[fl.of](head + 1)[fl.map](countUp)
})
console.log(
countUp(2).head, // 2
countUp(2).tail.run().head // 3
// ... etc
)
const fl = require('fantasy-land')
//- Lazy holds a vaue in a thunk, effectively delaying
//- evaluation until required. This is useful when we're
//- in a situation with either very large data set or
//- cyclical data.
//@ make stack-safe.
//> type Lazy a = Unit -> a
function Lazy(run) {
if (this.constructor !== Lazy)
return new Lazy(run)
this.run = run
}
/* Semigroup Lazy */ {
Lazy.prototype[fl.concat] = function (that) {
return Lazy(() => this.run()[fl.concat](that.run()))
}
}
// Monoid instance requires TypeRep
/* Functor Lazy */ {
Lazy.prototype[fl.map] = function (f) {
return Lazy(() => f(this.run()))
}
}
/* Apply Lazy */ {
Lazy.prototype[fl.ap] = function (that) {
return Lazy(() => that.run()(this.run()))
}
}
/* Applicative Lazy */ {
Lazy[fl.of] = value =>
Lazy(() => value)
}
/* Alt Lazy */ {
Lazy.prototype[fl.alt] = function (that) {
return Lazy(() => this.run().alt(that.run()))
}
}
// Plus instance requires TypeRep
/* Chain Lazy */ {
Lazy[fl.chain] = function (f) {
return Lazy(() => f(this.run()).run())
}
}
// Are Extend/Comonad useful here?
/* Extend Lazy */ {
Lazy[fl.extend] = function (f) {
return Lazy(() => f(this))
}
}
/* Comonad Lazy */ {
Lazy[fl.extract] = function () {
return this.run()
}
}
module.exports = Lazy
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment