Skip to content

Instantly share code, notes, and snippets.

@Sylvenas
Last active December 29, 2020 12:21
Show Gist options
  • 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

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