UNPKG

fluture

Version:

FantasyLand compliant (monadic) alternative to Promises

116 lines (106 loc) 3.4 kB
import show from 'sanctuary-show'; import type from 'sanctuary-type-identifiers'; import {Future, isFuture} from '../index.js'; import {strictEqual, deepStrictEqual} from 'assert'; const states = ['pending', 'crashed', 'rejected', 'resolved']; export const equality = a => b => { strictEqual(show(a), show(b)); deepStrictEqual(a, b); return true; }; export const future = x => { equality(isFuture(x))(true); equality(type(x))(Future['@@type']); return true; }; export function makeEquivalence (equals){ return function equivalence (ma){ return function (mb){ let astate = 0, bstate = 0, val; return new Promise(function (pass, fail){ future(ma); future(mb); function twice (m, x, s1, s2){ fail(new Error( 'A Future ' + states[s2] + ' after already having ' + states[s1] + '.\n' + ' First: Future({ <' + states[s1] + '> ' + show(val) + ' })\n' + ' Second: Future({ <' + states[s1] + '> ' + show(x) + ' })\n' + ' Future: ' + m.toString() )); } function assertInnerEqual (a, b){ if(astate === bstate){ if(isFuture(a) && isFuture(b)){ equivalence(a)(b).then(pass, fail); return; } try { equals(a)(b); pass(true); } catch (e){ inequivalent('The inner values are not equal: ' + e.message); } }else{ inequivalent( 'One Future ' + states[astate] + ', and the other Future ' + states[bstate] ); } function inequivalent (message){ fail(new Error( '\n ' + ma.toString() + ' :: Future({ <' + states[astate] + '> ' + show(a) + ' })' + '\n is not equivalent to:\n ' + mb.toString() + ' :: Future({ <' + states[bstate] + '> ' + show(b) + ' })\n\n' + message )); } } ma._interpret(function (x){ if(astate > 0) twice(ma, x, astate, 1); else { astate = 1; if(bstate > 0) assertInnerEqual(x, val); else val = x; } }, function (x){ if(astate > 0) twice(ma, x, astate, 2); else { astate = 2; if(bstate > 0) assertInnerEqual(x, val); else val = x; } }, function (x){ if(astate > 0) twice(ma, x, astate, 3); else { astate = 3; if(bstate > 0) assertInnerEqual(x, val); else val = x; } }); mb._interpret(function (x){ if(bstate > 0) twice(mb, x, bstate, 1); else { bstate = 1; if(astate > 0) assertInnerEqual(val, x); else val = x; } }, function (x){ if(bstate > 0) twice(mb, x, bstate, 2); else { bstate = 2; if(astate > 0) assertInnerEqual(val, x); else val = x; } }, function (x){ if(bstate > 0) twice(mb, x, bstate, 3); else { bstate = 3; if(astate > 0) assertInnerEqual(val, x); else val = x; } }); }); }; }; } export const equivalence = makeEquivalence(equality);