Skip to content

Commit

Permalink
update bimap implementation to reject result of leftFn, and improve t…
Browse files Browse the repository at this point in the history
…ype signature
  • Loading branch information
interacsean committed Mar 7, 2019
1 parent b37ec34 commit cfab316
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 33 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Standard Functions is a library aimed to fill in the gaps in the JS standard lib
## Functions

<dl>
<dt><a href="#bimap">bimap(leftFn, rightFn, p)</a> ⇒ <code>Promise.&lt;(T|never)&gt;</code></dt>
<dt><a href="#bimap">bimap(leftFn, rightFn, p)</a> ⇒ <code>Promise.&lt;(R|never)&gt;</code></dt>
<dd><p>Map over the success or error of a promise.</p>
</dd>
<dt><a href="#fmap">fmap(fn, p)</a> ⇒ <code>Promise.&lt;(T|never)&gt;</code></dt>
Expand Down Expand Up @@ -80,7 +80,7 @@ Works like the ! operator on the result of the function provided</p>

<a name="bimap"></a>

## bimap(leftFn, rightFn, p) ⇒ <code>Promise.&lt;(T\|never)&gt;</code>
## bimap(leftFn, rightFn, p) ⇒ <code>Promise.&lt;(R\|never)&gt;</code>
Map over the success or error of a promise.

**Kind**: global function
Expand Down Expand Up @@ -233,7 +233,8 @@ Call instance method of an object.
<a name="negate"></a>

## negate(fn) ⇒ <code>function</code>
Creates a function which negates the value of the result.Works like the ! operator on the result of the function provided
Creates a function which negates the value of the result.
Works like the ! operator on the result of the function provided

**Kind**: global function

Expand Down
4 changes: 2 additions & 2 deletions async/bimap/bimap.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ Object.defineProperty(exports, "__esModule", {
* @param leftFn {Function}
* @param rightFn {Function}
* @param p {Promise<T | never>}
* @returns {Promise<T | never>}
* @returns {Promise<R | never>}
*/
function bimap(leftFn, rightFn, p) {
return p.then(rightFn, leftFn);
return p.then(rightFn, e => Promise.reject(leftFn(e)));
}

exports.default = bimap;
12 changes: 6 additions & 6 deletions async/bimap/bimap.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
* @param leftFn {Function}
* @param rightFn {Function}
* @param p {Promise<T | never>}
* @returns {Promise<T | never>}
* @returns {Promise<R | never>}
*/
function bimap<T>(
leftFn: (Error) => any,
rightFn: (T) => any,
function bimap<T, R, E>(
leftFn: (E) => any,
rightFn: (T) => R,
p: Promise<T>
): Promise<T> {
return p.then(rightFn, leftFn);
): Promise<R> {
return p.then(rightFn, (e: E): Promise<R> => Promise.reject(leftFn(e)));
}

export default bimap;
63 changes: 63 additions & 0 deletions core/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,24 @@ Object.defineProperty(exports, "__esModule", {
value: true
});

var _always = require('./always/always');

Object.defineProperty(exports, 'always', {
enumerable: true,
get: function () {
return _interopRequireDefault(_always).default;
}
});

var _and = require('./and/and');

Object.defineProperty(exports, 'and', {
enumerable: true,
get: function () {
return _interopRequireDefault(_and).default;
}
});

var _compose = require('./compose/compose');

Object.defineProperty(exports, 'compose', {
Expand Down Expand Up @@ -49,6 +67,42 @@ Object.defineProperty(exports, 'identity', {
}
});

var _inst = require('./inst/inst');

Object.defineProperty(exports, 'inst', {
enumerable: true,
get: function () {
return _interopRequireDefault(_inst).default;
}
});

var _negate = require('./negate/negate');

Object.defineProperty(exports, 'negate', {
enumerable: true,
get: function () {
return _interopRequireDefault(_negate).default;
}
});

var _not = require('./not/not');

Object.defineProperty(exports, 'not', {
enumerable: true,
get: function () {
return _interopRequireDefault(_not).default;
}
});

var _or = require('./or/or');

Object.defineProperty(exports, 'or', {
enumerable: true,
get: function () {
return _interopRequireDefault(_or).default;
}
});

var _partial = require('./partial/partial');

Object.defineProperty(exports, 'partial', {
Expand All @@ -67,4 +121,13 @@ Object.defineProperty(exports, 'partialRight', {
}
});

var _trim = require('./trim/trim');

Object.defineProperty(exports, 'trim', {
enumerable: true,
get: function () {
return _interopRequireDefault(_trim).default;
}
});

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
8 changes: 8 additions & 0 deletions core/index.js.flow
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
// @flow

export { default as always } from './always/always';
export { default as and } from './and/and';
export { default as compose } from './compose/compose';
export { default as composeRight } from './composeRight/composeRight';
export { default as curry } from './curry/curry';
export { default as curryRight } from './curryRight/curryRight';
export { default as identity } from './identity/identity';
export { default as inst } from './inst/inst';
export { default as negate } from './negate/negate';
export { default as not } from './not/not';
export { default as or } from './or/or';
export { default as partial } from './partial/partial';
export { default as partialRight } from './partialRight/partialRight';
export { default as trim } from './trim/trim';

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"scripts": {
"test": "jest ./src",
"check": "eslint ./src && flow ./src",
"build": "yarn check && babel src/ -d ./ --ignore **/*spec.js && yarn build:docs && yarn build:types",
"build": "npm run check && babel src/ -d ./ --ignore **/*spec.js && npm run build:docs && npm run build:types",
"build:types": "flow-copy-source -v -i **/*spec.js src ./",
"build:docs": "node ./scripts/docs"
},
Expand Down
12 changes: 6 additions & 6 deletions src/async/bimap/bimap.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
* @param leftFn {Function}
* @param rightFn {Function}
* @param p {Promise<T | never>}
* @returns {Promise<T | never>}
* @returns {Promise<R | never>}
*/
function bimap<T>(
leftFn: (Error) => any,
rightFn: (T) => any,
function bimap<T, R, E>(
leftFn: (E) => any,
rightFn: (T) => R,
p: Promise<T>
): Promise<T> {
return p.then(rightFn, leftFn);
): Promise<R> {
return p.then(rightFn, (e: E): Promise<R> => Promise.reject(leftFn(e)));
}

export default bimap;
40 changes: 25 additions & 15 deletions src/async/bimap/bimap.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,37 @@
import bimap from './bimap';

describe('async/bimap', () => {
test('should only call left fn if promise rejects', async (): Promise<any> => {
const leftFn: Function = jest.fn();
test('should only call leftFn if promise rejects', async (done: Function): Promise<any> => {
const expected: Error = new Error('error');
const leftFn: Function = jest.fn().mockImplementation((v: number): Error => expected);
const rightFn: Function = jest.fn();

try {
await bimap(leftFn, rightFn, Promise.reject(1));
expect.assertions(3);

expect(leftFn).not.toHaveBeenCalled();
} catch (e) {
expect(e).not.toBeUndefined();
expect(rightFn).not.toHaveBeenCalled();
}
bimap(leftFn, rightFn, Promise.reject(3))
.then(done)
.catch((actual: Error) => {
expect(actual).toBe(expected);
expect(leftFn).toHaveBeenCalled();
expect(rightFn).not.toHaveBeenCalled();
done();
});
});

test('should only call rightFn if promise resolves', async (): Promise<any> => {
test('should only call rightFn if promise resolves', async (done: Function): Promise<any> => {
const expected: number = 6;
const leftFn: Function = jest.fn();
const rightFn: Function = jest.fn();
const rightFn: Function = jest.fn().mockImplementation((v: number): number => expected);

await bimap(leftFn, rightFn, Promise.resolve(1));
expect.assertions(3);

expect(leftFn).not.toHaveBeenCalled();
expect(rightFn).toHaveBeenCalled();
bimap(leftFn, rightFn, Promise.resolve(1))
.then((actual: number) => {
expect(actual).toBe(expected);
expect(leftFn).not.toHaveBeenCalled();
expect(rightFn).toHaveBeenCalled();
done();
})
.catch(done);
});
});
});

0 comments on commit cfab316

Please sign in to comment.