Skip to content

Instantly share code, notes, and snippets.

@Sylvenas
Last active December 29, 2020 12:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Sylvenas/2a06088257344bc1596ed03407194f49 to your computer and use it in GitHub Desktop.
Save Sylvenas/2a06088257344bc1596ed03407194f49 to your computer and use it in GitHub Desktop.
Functional programming Task async in parallel
// Task(functor,applicative,monad)
const Task = fork => ({
map: f => Task((reject, resolve) =>
fork(reject, a => resolve(f(a)))),
ap: fn =>
Task((reject, resolve) => fork(reject, a =>
fn.map(a).fork(reject, resolve)
)),
chain: f =>
Task((reject, resolve) => fork(reject, a =>
f(a).fork(reject, resolve))),
fork,
[Symbol.for('nodejs.util.inspect.custom')]: () => 'Task(?)'
})
// lift
Task.of = a => Task((_, resolve) => resolve(a))
// --------------------------async------------
// async get user name
const fetchName = Task((_, resolve) => {
setTimeout(() => {
resolve('Melo')
}, 2000)
});
// async get user age
const fetchAge = Task((_, resolve) => {
setTimeout(() => {
resolve(24)
}, 2000)
});
// pure app
const app = Task
.of(name => age => ({ name, age }))
.ap(fetchName)
.ap(fetchAge)
// effect
app.fork(() => {
console.log('something went wrong')
}, x => {
console.log('x', x) // 4 seconds later log {name:'Melo', age:24}
})
@Sylvenas
Copy link
Author

Great post! Thanks.

Do you have a plan to put all posts on github? I can do the translation (chinese) work.

@ivenmarquardt
Copy link

I will actually need a Mandarin translation for my course on Github at some point. However, for the time being everything is still in flux, chapters are revised. Translating it makes only sense when things get more stable.

@Sylvenas
Copy link
Author

Sylvenas commented Dec 29, 2020

Similar to Promise.all. But the ap function only needs to receive one Task.

const Task = fork => ({
    ap: fn => Task((reject, resolve) => {
          let func, rejected
          const firstState = fork(x => {
              rejected = true;
              return reject(x)
          }, x => func = x)
          const senondState = fn.fork(x => {
              rejected = true;
              return reject(x)
          }, x => {
              if (rejected) return
              return resolve(func(x))
          })
          return [firstState, senondState]
      })
})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment