JSPM

js-monadic

0.1.7
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 4
  • Score
    100M100P100Q23341F
  • License MIT

Monad with do notation in Javascript, using ES6 generators.

Package Exports

  • js-monadic

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (js-monadic) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

js-monadic

Monad with do notation in Javascript, using ES6 generators.

Installing

Using npm:

$ npm install js-monadic

Using yarn:

$ yarn add js-monadic

Using unpkg CDN:

<script src="https://unpkg.com/js-monadic/umd/js-monadic.min.js"></script>

Usage

const Monad = require('js-monadic')

// Unit/Return function of the monad
function unit(v) {
    // ...
}

// Bind function of the monad
function bind(v, f) {
    // ...
}

const MyMonad = Monad(unit, bind)

// Same as calling unit(...)
const val = MyMonad(/* ... */)

MyMonad.do(function*() {
    const foo = yield MyMonad(/* ... */)
    // ...
}())

Example

Option / Maybe

// type Option<T> = { some: T } | null
const Option = Monad(
  (value) => value === null ? null : { some: value },
  (option, fn) => option === null ? null : fn(option.some)
)

const foo = Option.do(function*() {
    const a = yield Option(1) // a = 1
    const b = yield Option(2) // b = 2
    const c = yield Option(3) // c = 3
    return Option(a + b + c)
}())
// foo = { some: 6 }

const bar = Option.do(function*() {
    const a = yield Option(1)     // a = 1
    const b = yield Option(null)
    // will not reach here at all because the function in
    // the second argument of "bind" was not called when
    // evaluating Option(null), therefore the chain stops here
    const c = yield Option(3)
    return Option(a + b + c)
}())
// bar = null

Result / Either

// type Result<T> = { ok: T } | { error: Error }
const Result = Monad(
  (value) => value instanceof Error ? { error: value } : { ok: value },
  (result, fn) => 'error' in result ? result : fn(result.ok)
)

const foo = Result.do(function*() {
    const a = yield Result(1) // a = 1
    const b = yield Result(2) // b = 2
    return Result(a + b)
}())
// foo = { ok: 3 }

const bar = Result.do(function*() {
    const a = yield Result(1) // a = 1
    const b = yield Result(new Error('Bad object'))
    // will not reach here
    return Result(a + b)
}())
// bar = { error: Error('Bad object') }

Promise

// type Future<T> = Promise<T>
const Future = Monad(
  (value) => Promsie.resolve(value),
  (result, fn) => result.then(fn)
)

const foo = Future.do(function*() {
    const a = yield Promise.resolve(1) // a = 1
    const b = yield Promise.resolve(2) // b = 2
    return Promise.resolve(a + b)
}())
// foo = Promise { 3 }

const bar = Future.do(function*() {
    const a = yield Promise.resolve(1) // a = 1
    const b = yield Promise.reject('Bad object')
    // will not reach here
    return Promise.resolve(a + b)
}())
// bar = Promise { <rejected> 'Bad object' }