UNPKG

@fpjs/overture

Version:
63 lines (55 loc) 2.11 kB
// This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. /** * Callback wraps a Node.js-style callback function to provide functor, * applicative and monadic operations on it. * * Like all callback-style functions, it short-circuits computation upon the * first error. */ import {rapply, type} from "@fpjs/overture/base"; import {map} from "@fpjs/overture/algebras/functor"; /** Build a continuation on a callback function. */ ///:: ((e, a) -> ()) -> (a -> ((e, b) -> ())) -> ((e, b) -> ()) -> () const mkcont = (cb) => (f) => (done) => cb((err, x) => (err != null) ? done(err) : f(x)(done)); ///:: ((e, a) -> ()) -> Callback e a export const Callback = (cb) => ({ '@@type': 'Callback', 'constructor': Callback, '_callback': cb, 'fantasy-land/map': (f) => Callback( mkcont (cb) ((x) => (done) => done (null, f (x))) ), 'fantasy-land/ap': (ab) => Callback( mkcont (cb) ((x) => (map (rapply (x)) (ab))['_callback']) ), 'fantasy-land/chain': (f) => Callback( mkcont (cb) ((x) => f(x)['_callback']) ), }); Callback['fantasy-land/of'] = (x) => Callback((done) => done(null, x)); /** Run a Callback and process it's result with a callback-style function. */ ///:: ((e, a) -> ()) -> Callback e a -> () export const runCallback = (f) => (o) => { const op = o['_callback']; if (op === undefined) { throw TypeError(`${type(o)} is not Callback`); } return op (f); }; /** Constructor for a Callback with an error. */ ///:: (e) => Callback e a export const error = (e) => Callback ((done) => done(e)); /** Recover from specific errors. */ ///:: (e -> Callback e a) -> Callback e a -> Callback e a export const recover = (f) => (o) => { const cb = o['_callback']; if (cb === undefined) { throw TypeError(`${type(o)} is not Callback`); } return Callback ((done) => cb ( (e, r) => e === null ? done(null, r) : (runCallback (done) (f (e))) )); };