concurrify
Advanced tools
Comparing version 1.0.3 to 1.1.0
267
index.js
@@ -1,13 +0,72 @@ | ||
(function(f){ | ||
//. # Concurrify | ||
//. | ||
//. [![Chat](https://badges.gitter.im/fluture-js/concurrify.svg)](https://gitter.im/fluture-js/fluture) | ||
//. [![NPM Version](https://badge.fury.io/js/concurrify.svg)](https://www.npmjs.com/package/concurrify) | ||
//. [![Dependencies](https://david-dm.org/fluture-js/concurrify.svg)](https://david-dm.org/fluture-js/concurrify) | ||
//. [![Build Status](https://travis-ci.org/fluture-js/concurrify.svg?branch=master)](https://travis-ci.org/fluture-js/concurrify) | ||
//. [![Code Coverage](https://codecov.io/gh/fluture-js/concurrify/branch/master/graph/badge.svg)](https://codecov.io/gh/fluture-js/concurrify) | ||
//. | ||
//. Turn non-concurrent [FantasyLand 3][FL3] Applicatives concurrent. | ||
//. | ||
//. Most time-dependent applicatives are very useful as Monads, because it | ||
//. gives them the ability to run sequentially, where each step depends on the | ||
//. previous. However, they lose the ability to run concurrently. This library | ||
//. allows one to wrap a [`Monad`][FL:Monad] (with sequential `ap`) in an | ||
//. [`Alternative`][FL:Alternative] (with parallel `ap`). | ||
//. | ||
//. ## Usage | ||
//. | ||
//. ```js | ||
//. // The concurrify function takes four arguments, explained below. | ||
//. const concurrify = require ('concurrify'); | ||
//. | ||
//. // The Type Representative of the Applicative we want to transform. | ||
//. const Future = require ('fluture'); | ||
//. | ||
//. // A "zero" instance and an "alt" function for "Alternative". | ||
//. const zero = Future (() => {}); | ||
//. const alt = Future.race; | ||
//. | ||
//. // An override "ap" function that runs the Applicatives concurrently. | ||
//. const ap = (mx, mf) => (Future.both (mx, mf)).map (([x, f]) => f (x)); | ||
//. | ||
//. // A new Type Representative created by concurrify. | ||
//. const ConcurrentFuture = concurrify (Future, zero, alt, ap); | ||
//. | ||
//. // We can use our type as such: | ||
//. const par = ConcurrentFuture (Future.of (1)); | ||
//. const seq = par.sequential; | ||
//. seq.fork (console.error, console.log); | ||
//. ``` | ||
//. | ||
//. ## Interoperability | ||
//. | ||
//. * Implements [FantasyLand 3][FL3] `Alternative` | ||
//. (`of`, `zero`, `map`, `ap`, `alt`). | ||
//. * Instances can be identified by, and are compared using, | ||
//. [Sanctuary Type Identifiers][STI]. | ||
//. * Instances can be converted to String representations according to | ||
//. [Sanctuary Show][SS]. | ||
//. | ||
//. ## API | ||
(function(f) { | ||
'use strict'; | ||
/*istanbul ignore next*/ | ||
if(typeof module === 'object' && typeof module.exports === 'object'){ | ||
module.exports = f(require('sanctuary-type-classes'), require('sanctuary-type-identifiers')); | ||
}else{ | ||
self.concurrify = f(self.sanctuaryTypeClasses, self.sanctuaryTypeIdentifiers); | ||
/* istanbul ignore next */ | ||
if (typeof module === 'object' && typeof module.exports === 'object') { | ||
module.exports = f ( | ||
require ('sanctuary-show'), | ||
require ('sanctuary-type-classes'), | ||
require ('sanctuary-type-identifiers') | ||
); | ||
} else { | ||
self.concurrify = f ( | ||
self.sanctuaryShow, | ||
self.sanctuaryTypeClasses, | ||
self.sanctuaryTypeIdentifiers | ||
); | ||
} | ||
}(function(Z, type){ | ||
} (function(show, Z, type) { | ||
@@ -22,16 +81,20 @@ 'use strict'; | ||
var $$type = '@@type'; | ||
var $$show = '@@show'; | ||
var ordinal = ['first', 'second', 'third', 'fourth', 'fifth']; | ||
function isFunction(f){ | ||
// isFunction :: Any -> Boolean | ||
function isFunction(f) { | ||
return typeof f === 'function'; | ||
} | ||
function isBinary(f){ | ||
// isBinary :: Function -> Boolean | ||
function isBinary(f) { | ||
return f.length >= 2; | ||
} | ||
function isApplicativeRepr(Repr){ | ||
try{ | ||
return Z.Applicative.test(Z.of(Repr)); | ||
}catch(_){ | ||
// isApplicativeRepr :: TypeRepr -> Boolean | ||
function isApplicativeRepr(Repr) { | ||
try { | ||
return Z.Applicative.test (Z.of (Repr)); | ||
} catch (_) { | ||
return false; | ||
@@ -41,4 +104,5 @@ } | ||
function invalidArgument(it, at, expected, actual){ | ||
throw new TypeError( | ||
// invalidArgument :: (String, Number, String, String) -> !Undefined | ||
function invalidArgument(it, at, expected, actual) { | ||
throw new TypeError ( | ||
it | ||
@@ -50,98 +114,153 @@ + ' expects its ' | ||
+ '\n Actual: ' | ||
+ Z.toString(actual) | ||
+ show (actual) | ||
); | ||
} | ||
function invalidContext(it, actual, an){ | ||
throw new TypeError( | ||
it + ' was invoked outside the context of a ' + an + '. \n Called on: ' + Z.toString(actual) | ||
// invalidContext :: (String, String, String) -> !Undefined | ||
function invalidContext(it, actual, an) { | ||
throw new TypeError ( | ||
it | ||
+ ' was invoked outside the context of a ' | ||
+ an | ||
+ '. \n Called on: ' | ||
+ show (actual) | ||
); | ||
} | ||
// getTypeIdentifier :: TypeRepresentative -> TypeIdentifier | ||
function getTypeIdentifier(Repr){ | ||
// getTypeIdentifier :: TypeRepresentative -> String | ||
function getTypeIdentifier(Repr) { | ||
return Repr[$$type] || Repr.name || 'Anonymous'; | ||
} | ||
// generateTypeIdentifier :: TypeIdentifier -> TypeIdentifier | ||
function generateTypeIdentifier(identifier){ | ||
var o = type.parse(identifier); | ||
return (o.namespace || 'concurrify') + '/Concurrent' + o.name + '@' + o.version; | ||
// generateTypeIdentifier :: String -> String | ||
function generateTypeIdentifier(identifier) { | ||
var o = type.parse (identifier); | ||
return ( | ||
(o.namespace || 'concurrify') + '/Concurrent' + o.name + '@' + o.version | ||
); | ||
} | ||
//concurrify :: Applicative m | ||
// => (TypeRep m, m a, (m a, m a) -> m a, (m a, m (a -> b)) -> m b) | ||
// -> Concurrently m | ||
return function concurrify(Repr, zero, alt, ap){ | ||
//# concurrify :: (Applicative f, Alternative (m f)) => (TypeRep f, f a, (f a, f a) -> f a, (f a, f (a -> b)) -> f b) -> f c -> m f c | ||
return function concurrify(Repr, zero, alt, ap) { | ||
var INNERTYPE = getTypeIdentifier(Repr); | ||
var OUTERTYPE = generateTypeIdentifier(INNERTYPE); | ||
var INNERNAME = type.parse(INNERTYPE).name; | ||
var OUTERNAME = type.parse(OUTERTYPE).name; | ||
var INNERTYPE = getTypeIdentifier (Repr); | ||
var OUTERTYPE = generateTypeIdentifier (INNERTYPE); | ||
var INNERNAME = (type.parse (INNERTYPE)).name; | ||
var OUTERNAME = (type.parse (OUTERTYPE)).name; | ||
function Concurrently(sequential){ | ||
function Concurrently(sequential) { | ||
this.sequential = sequential; | ||
} | ||
function isInner(x){ | ||
return x instanceof Repr | ||
|| (Boolean(x) && x.constructor === Repr) | ||
|| type(x) === Repr[$$type]; | ||
function isInner(x) { | ||
return ( | ||
(x instanceof Repr) || | ||
(Boolean (x) && x.constructor === Repr) || | ||
(type (x) === Repr[$$type]) | ||
); | ||
} | ||
function isOuter(x){ | ||
return x instanceof Concurrently | ||
|| (Boolean(x) && x.constructor === Concurrently) | ||
|| type(x) === OUTERTYPE; | ||
function isOuter(x) { | ||
return ( | ||
(x instanceof Concurrently) || | ||
(Boolean (x) && x.constructor === Concurrently) || | ||
(type (x) === OUTERTYPE) | ||
); | ||
} | ||
function construct(x){ | ||
if(!isInner(x)) invalidArgument(OUTERNAME, 0, 'be of type "' + INNERNAME + '"', x); | ||
return new Concurrently(x); | ||
function construct(x) { | ||
if (!isInner (x)) { | ||
invalidArgument (OUTERNAME, 0, 'be of type "' + INNERNAME + '"', x); | ||
} | ||
return new Concurrently (x); | ||
} | ||
if(!isApplicativeRepr(Repr)) invalidArgument('concurrify', 0, 'represent an Applicative', Repr); | ||
if(!isInner(zero)) invalidArgument('concurrify', 1, 'be of type "' + INNERNAME + '"', zero); | ||
if(!isFunction(alt)) invalidArgument('concurrify', 2, 'be a function', alt); | ||
if(!isBinary(alt)) invalidArgument('concurrify', 2, 'be binary', alt); | ||
if(!isFunction(ap)) invalidArgument('concurrify', 3, 'be a function', ap); | ||
if(!isBinary(ap)) invalidArgument('concurrify', 3, 'be binary', ap); | ||
if (!isApplicativeRepr (Repr)) { | ||
invalidArgument ('concurrify', 0, 'represent an Applicative', Repr); | ||
} | ||
var proto = Concurrently.prototype = construct.prototype = {constructor: construct}; | ||
if (!isInner (zero)) { | ||
invalidArgument | ||
('concurrify', 1, 'be of type "' + INNERNAME + '"', zero); | ||
} | ||
if (!isFunction (alt)) { | ||
invalidArgument ('concurrify', 2, 'be a function', alt); | ||
} | ||
if (!isBinary (alt)) { | ||
invalidArgument ('concurrify', 2, 'be binary', alt); | ||
} | ||
if (!isFunction (ap)) { | ||
invalidArgument ('concurrify', 3, 'be a function', ap); | ||
} | ||
if (!isBinary (ap)) { | ||
invalidArgument ('concurrify', 3, 'be binary', ap); | ||
} | ||
var proto = | ||
Concurrently.prototype = | ||
construct.prototype = {constructor: construct}; | ||
construct[$$type] = OUTERTYPE; | ||
var mzero = new Concurrently(zero); | ||
var mzero = new Concurrently (zero); | ||
construct[$zero] = function Concurrently$zero(){ | ||
construct[$zero] = function Concurrently$zero() { | ||
return mzero; | ||
}; | ||
construct[$of] = function Concurrently$of(value){ | ||
return new Concurrently(Z.of(Repr, value)); | ||
construct[$of] = function Concurrently$of(value) { | ||
return new Concurrently (Z.of (Repr, value)); | ||
}; | ||
proto[$map] = function Concurrently$map(mapper){ | ||
if(!isOuter(this)) invalidContext(OUTERNAME + '#map', this, OUTERNAME); | ||
if(!isFunction(mapper)) invalidArgument(OUTERNAME + '#map', 0, 'be a function', mapper); | ||
return new Concurrently(Z.map(mapper, this.sequential)); | ||
proto[$map] = function Concurrently$map(mapper) { | ||
if (!isOuter (this)) { | ||
invalidContext (OUTERNAME + '#map', this, OUTERNAME); | ||
} | ||
if (!isFunction (mapper)) { | ||
invalidArgument (OUTERNAME + '#map', 0, 'be a function', mapper); | ||
} | ||
return new Concurrently (Z.map (mapper, this.sequential)); | ||
}; | ||
proto[$ap] = function Concurrently$ap(m){ | ||
if(!isOuter(this)) invalidContext(OUTERNAME + '#ap', this, OUTERNAME); | ||
if(!isOuter(m)) invalidArgument(OUTERNAME + '#ap', 0, 'be a ' + OUTERNAME, m); | ||
return new Concurrently(ap(this.sequential, m.sequential)); | ||
proto[$ap] = function Concurrently$ap(m) { | ||
if (!isOuter (this)) { | ||
invalidContext (OUTERNAME + '#ap', this, OUTERNAME); | ||
} | ||
if (!isOuter (m)) { | ||
invalidArgument (OUTERNAME + '#ap', 0, 'be a ' + OUTERNAME, m); | ||
} | ||
return new Concurrently (ap (this.sequential, m.sequential)); | ||
}; | ||
proto[$alt] = function Concurrently$alt(m){ | ||
if(!isOuter(this)) invalidContext(OUTERNAME + '#alt', this, OUTERNAME); | ||
if(!isOuter(m)) invalidArgument(OUTERNAME + '#alt', 0, 'be a ' + OUTERNAME, m); | ||
return new Concurrently(alt(this.sequential, m.sequential)); | ||
proto[$alt] = function Concurrently$alt(m) { | ||
if (!isOuter (this)) { | ||
invalidContext (OUTERNAME + '#alt', this, OUTERNAME); | ||
} | ||
if (!isOuter (m)) { | ||
invalidArgument (OUTERNAME + '#alt', 0, 'be a ' + OUTERNAME, m); | ||
} | ||
return new Concurrently (alt (this.sequential, m.sequential)); | ||
}; | ||
proto.toString = function Concurrently$toString(){ | ||
if(!isOuter(this)) invalidContext(OUTERNAME + '#toString', this, OUTERNAME); | ||
return OUTERNAME + '(' + Z.toString(this.sequential) + ')'; | ||
proto[$$show] = function Concurrently$show() { | ||
return OUTERNAME + '(' + show (this.sequential) + ')'; | ||
}; | ||
proto.toString = function Concurrently$toString() { | ||
if (!isOuter (this)) { | ||
invalidContext (OUTERNAME + '#toString', this, OUTERNAME); | ||
} | ||
return this[$$show] (); | ||
}; | ||
return construct; | ||
@@ -152,1 +271,7 @@ | ||
})); | ||
//. [FL3]: https://github.com/fantasyland/fantasy-land/ | ||
//. [FL:Monad]: https://github.com/fantasyland/fantasy-land/#monad | ||
//. [FL:Alternative]: https://github.com/fantasyland/fantasy-land/#alternative | ||
//. [STI]: https://github.com/sanctuary-js/sanctuary-type-identifiers | ||
//. [SS]: https://github.com/sanctuary-js/sanctuary-show |
{ | ||
"name": "concurrify", | ||
"version": "1.0.3", | ||
"version": "1.1.0", | ||
"description": "Turn non-concurrent FantasyLand Applicatives concurrent", | ||
"main": "index.js", | ||
"repository": "https://github.com/fluture-js/concurrify.git", | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/fluture-js/concurrify.git" | ||
}, | ||
"scripts": { | ||
"clean": "rimraf npm-debug.log .nyc_output coverage.lcov", | ||
"lint": "eslint index.js test", | ||
"release": "npm outdated --long && xyz --edit --repo git@github.com:fluture-js/concurrify.git --tag 'X.Y.Z' --increment", | ||
"test": "npm run lint && npm run test:unit", | ||
"test:unit": "nyc mocha --ui bdd --reporter list --check-leaks --full-trace test/**.test.js", | ||
"test:coverage": "nyc report --reporter=text-lcov > coverage.lcov && codecov" | ||
"doctest": "sanctuary-doctest", | ||
"lint": "sanctuary-lint", | ||
"release": "sanctuary-release", | ||
"test": "npm run lint && sanctuary-test && npm run doctest" | ||
}, | ||
@@ -22,3 +23,3 @@ "author": "Aldwin Vlasblom <aldwin.vlasblom@gmail.com> (https://github.com/Avaq)", | ||
"engines": { | ||
"node": ">=4.0.0" | ||
"node": ">=6.0.0" | ||
}, | ||
@@ -42,4 +43,11 @@ "keywords": [ | ||
], | ||
"files": [ | ||
"/index.js", | ||
"/LICENSE", | ||
"/package.json", | ||
"/README.md" | ||
], | ||
"dependencies": { | ||
"sanctuary-type-classes": "^8.0.0", | ||
"sanctuary-show": "^1.0.0", | ||
"sanctuary-type-classes": "^9.0.0", | ||
"sanctuary-type-identifiers": "^2.0.0" | ||
@@ -50,10 +58,5 @@ }, | ||
"codecov": "^3.0.0", | ||
"eslint": "^4.14.0", | ||
"eslint-config-warp": "^2.1.0", | ||
"fantasy-land": "^3.4.0", | ||
"mocha": "^4.0.0", | ||
"nyc": "^11.4.1", | ||
"rimraf": "^2.6.2", | ||
"xyz": "^3.0.0" | ||
"sanctuary-scripts": "^2.0.0" | ||
} | ||
} |
@@ -11,6 +11,6 @@ # Concurrify | ||
Most time-dependent applicatives are very useful as Monads, because it gives | ||
them the ability to run sequentially, where each step depends on the previous. | ||
However, they lose the ability to run concurrently. This library allows one to | ||
wrap a [`Monad`][FL:Monad] (with sequential `ap`) in an | ||
Most time-dependent applicatives are very useful as Monads, because it | ||
gives them the ability to run sequentially, where each step depends on the | ||
previous. However, they lose the ability to run concurrently. This library | ||
allows one to wrap a [`Monad`][FL:Monad] (with sequential `ap`) in an | ||
[`Alternative`][FL:Alternative] (with parallel `ap`). | ||
@@ -21,42 +21,41 @@ | ||
```js | ||
//The concurrify function takes four arguments, explained below. | ||
const concurrify = require('concurrify'); | ||
// The concurrify function takes four arguments, explained below. | ||
const concurrify = require ('concurrify'); | ||
//We load the Type Representative of the Applicative we want to transform. | ||
const Future = require('fluture'); | ||
// The Type Representative of the Applicative we want to transform. | ||
const Future = require ('fluture'); | ||
//We create a "zero" instance and an "alt" function for "Alternative". | ||
const zero = Future(() => {}); | ||
// A "zero" instance and an "alt" function for "Alternative". | ||
const zero = Future (() => {}); | ||
const alt = Future.race; | ||
//We create an override "ap" function that runs the Applicatives concurrently. | ||
const ap = (mx, mf) => Future.both(mx, mf).map(([x, f]) => f(x)); | ||
// An override "ap" function that runs the Applicatives concurrently. | ||
const ap = (mx, mf) => (Future.both (mx, mf)).map (([x, f]) => f (x)); | ||
//Calling concurrify with these arguments gives us a new Type Representative. | ||
const ConcurrentFuture = concurrify(Future, zero, alt, ap); | ||
// A new Type Representative created by concurrify. | ||
const ConcurrentFuture = concurrify (Future, zero, alt, ap); | ||
//We can use our type as such: | ||
ConcurrentFuture(Future.of(1)).sequential.fork(console.error, console.log); | ||
// We can use our type as such: | ||
const par = ConcurrentFuture (Future.of (1)); | ||
const seq = par.sequential; | ||
seq.fork (console.error, console.log); | ||
``` | ||
## API | ||
## Interoperability | ||
```hs | ||
concurrify :: (Applicative f, Alternative (m f)) | ||
=> (TypeRep f, f a, (f a, f a) -> f a, (f a, f (a -> b)) -> f b) | ||
-> f c | ||
-> m f c | ||
``` | ||
* Implements [FantasyLand 3][FL3] `Alternative` | ||
(`of`, `zero`, `map`, `ap`, `alt`). | ||
* Instances can be identified by, and are compared using, | ||
[Sanctuary Type Identifiers][STI]. | ||
* Instances can be converted to String representations according to | ||
[Sanctuary Show][SS]. | ||
## Interoperability | ||
## API | ||
* Implements [FantasyLand 3][FL3] `Alternative` (`of`, `zero`, `map`, `ap`, `alt`). | ||
* Instances can be identified by, and are compared using, [Sanctuary Type Identifiers][STI]. | ||
#### <a name="concurrify" href="https://github.com/fluture-js/concurrify/blob/v1.1.0/index.js#L140">`concurrify :: (Applicative f, Alternative (m f)) => (TypeRep f, f a, (f a, f a) -> f a, (f a, f (a -> b)) -> f b) -> f c -> m f c`</a> | ||
<!-- References --> | ||
[FL3]: https://github.com/fantasyland/fantasy-land/ | ||
[FL:Monad]: https://github.com/fantasyland/fantasy-land/#monad | ||
[FL:Alternative]: https://github.com/fantasyland/fantasy-land/#alternative | ||
[STI]: https://github.com/sanctuary-js/sanctuary-type-identifiers | ||
[SS]: https://github.com/sanctuary-js/sanctuary-show |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
4
0
13162
3
4
229
60
1
+ Addedsanctuary-show@^1.0.0
+ Addedsanctuary-show@1.0.0(transitive)
+ Addedsanctuary-type-classes@9.0.0(transitive)
- Removedsanctuary-type-classes@8.2.1(transitive)