@safareli/free
Version:
Combination of a free applicative functor and free monad
1,629 lines (1,490 loc) • 51.8 kB
JavaScript
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define([], factory);
else if(typeof exports === 'object')
exports["Free"] = factory();
else
root["Free"] = factory();
})(this, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
var _require = __webpack_require__(1),
of = _require.of,
map = _require.map,
ap = _require.ap,
chain = _require.chain;
var patchAll = __webpack_require__(3);
// data Free i a
// = Ap { x: (Free i b), y: (Free i (b -> a)) }
// | Pure { x: a }
// | Lift { x: i, f: (b -> a) }
// | Chain { x: (Free i b), f: (b -> (Free i a)) }
function Free() {
throw new TypeError('No direct use of Free constructor is Allowed');
}
function Pure(x) {
if (!(this instanceof Pure)) {
return new Pure(x);
}
this.x = x;
}
Pure.prototype = Object.create(Free.prototype);
Pure.prototype.constructor = Pure;
Pure.prototype.cata = function (d) {
return d.Pure(this.x);
};
function Lift(x, f) {
if (!(this instanceof Lift)) {
return new Lift(x, f);
}
this.x = x;
this.f = f;
}
Lift.prototype = Object.create(Free.prototype);
Lift.prototype.constructor = Lift;
Lift.prototype.cata = function (d) {
return d.Lift(this.x, this.f);
};
function Ap(x, y) {
if (!(this instanceof Ap)) {
return new Ap(x, y);
}
this.x = x;
this.y = y;
}
Ap.prototype = Object.create(Free.prototype);
Ap.prototype.constructor = Ap;
Ap.prototype.cata = function (d) {
return d.Ap(this.x, this.y);
};
function Chain(x, f) {
if (!(this instanceof Chain)) {
return new Chain(x, f);
}
this.x = x;
this.f = f;
}
Chain.prototype = Object.create(Free.prototype);
Chain.prototype.constructor = Chain;
Chain.prototype.cata = function (d) {
return d.Chain(this.x, this.f);
};
Free.Pure = Pure;
Free.Ap = Ap;
Free.Lift = Lift;
Free.Chain = Chain;
var compose = function compose(f, g) {
return function (x) {
return f(g(x));
};
};
var id = function id(x) {
return x;
};
/* istanbul ignore next */
Free.Pure.toString = function () {
return 'Free.Pure';
};
/* istanbul ignore next */
Free.Ap.toString = function () {
return 'Free.Ap';
};
/* istanbul ignore next */
Free.Lift.toString = function () {
return 'Free.Lift';
};
/* istanbul ignore next */
Free.Chain.toString = function () {
return 'Free.Chain';
};
/* istanbul ignore next */
Free.prototype.toString = function () {
return this.cata({
Pure: function Pure(x) {
return 'Free.Pure(' + x + ')';
},
Lift: function Lift(x, f) {
return 'Free.Lift(' + x + ',=>)';
},
Ap: function Ap(x, y) {
return 'Free.Ap(' + x + ',' + y + ')';
},
Chain: function Chain(x, f) {
return 'Free.Chain(' + x + ',=>)';
}
});
};
Free.of = Free.Pure;
Free.liftF = function (command) {
return Free.Lift(command, id);
};
Free.prototype.map = function (f) {
return this.cata({
Pure: function Pure(x) {
return Free.Pure(f(x));
},
Lift: function Lift(x, g) {
return Free.Lift(x, compose(f, g));
},
Ap: function Ap(x, y) {
return Free.Ap(x, map(function (a) {
return map(f, a);
}, y));
},
Chain: function Chain(x, g) {
return Free.Chain(x, function (a) {
return map(f, g(a));
});
}
});
};
Free.prototype.ap = function (y) {
var _this = this;
return this.cata({
Pure: function Pure(x) {
return map(function (f) {
return f(x);
}, y);
},
Ap: function Ap() {
return Free.Ap(_this, y);
},
Lift: function Lift() {
return Free.Ap(_this, y);
},
Chain: function Chain() {
return Free.Ap(_this, y);
}
});
};
Free.prototype.chain = function (f) {
var _this2 = this;
return this.cata({
Pure: function Pure(x) {
return f(x);
},
Ap: function Ap() {
return Free.Chain(_this2, f);
},
Lift: function Lift() {
return Free.Chain(_this2, f);
},
Chain: function Chain(x, g) {
return Free.Chain(x, function (v) {
return chain(f, g(v));
});
}
});
};
Free.prototype.hoist = function (f) {
return this.foldMap(compose(Free.liftF, f), Free);
};
Free.prototype.retract = function (m) {
return this.foldMap(id, m);
};
Free.prototype.foldMap = function (f, m) {
return m.chainRec(function (next, done, v) {
return v.cata({
Pure: function Pure(x) {
return map(done, of(m, x));
},
Lift: function Lift(x, g) {
return map(compose(done, g), f(x));
},
Ap: function Ap(x, y) {
return map(done, ap(y.foldMap(f, m), x.foldMap(f, m)));
},
Chain: function Chain(x, g) {
return map(compose(next, g), x.foldMap(f, m));
}
});
}, this);
};
Free.prototype.graft = function (f) {
return this.foldMap(f, Free);
};
var chainRecNext = function chainRecNext(value) {
return { done: false, value: value };
};
var chainRecDone = function chainRecDone(value) {
return { done: true, value: value };
};
Free.chainRec = function (f, i) {
return chain(function (_ref) {
var done = _ref.done,
value = _ref.value;
return done ? Free.of(value) : Free.chainRec(f, value);
}, f(chainRecNext, chainRecDone, i));
};
patchAll([Free, Free.prototype]);
module.exports = Free;
/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*
############ #
############ ###
##### #####
##### ####################
##### ######################
##### ###########
##### ######################
##### ####################
##### #####
############ ###
############ */
//. # sanctuary-type-classes
//.
//. The [Fantasy Land Specification][FL] "specifies interoperability of common
//. algebraic structures" by defining a number of type classes. For each type
//. class, it states laws which every member of a type must obey in order for
//. the type to be a member of the type class. In order for the Maybe type to
//. be considered a [Functor][], for example, every `Maybe a` value must have
//. a `fantasy-land/map` method which obeys the identity and composition laws.
//.
//. This project provides:
//.
//. - [`TypeClass`](#TypeClass), a function for defining type classes;
//. - one `TypeClass` value for each Fantasy Land type class;
//. - lawful Fantasy Land methods for JavaScript's built-in types;
//. - one function for each Fantasy Land method; and
//. - several functions derived from these functions.
//.
//. ## Type-class hierarchy
//.
//. <pre>
//: Setoid Semigroup Foldable Functor Extend
//: (equals) (concat) (reduce) (map) (extend)
//: | \ / | | | \ /
//: | \ / | | | \ /
//: | \ / | | | \ /
//: | \ / | | | \ /
//: | \ / | | | \ /
//: | \ / | | | \ /
//: | \ / / | \ \ /
//: Monoid Traversable / | \ Comonad
//: (empty) (traverse) / | \ (extract)
//: / | \
//: Bifunctor Apply Profunctor
//: (bimap) (ap) (promap)
//: / \
//: / \
//: / \
//: / \
//: / \
//: Applicative Chain
//: (of) (chain)
//: \ / \
//: \ / \
//: \ / \
//: \ / \
//: \ / \
//: Monad ChainRec
//: (chainRec)
//. </pre>
//.
//. ## API
(function(f) {
'use strict';
/* istanbul ignore else */
if (typeof module === 'object' && typeof module.exports === 'object') {
module.exports = f();
} else if ("function" === 'function' && __webpack_require__(2) != null) {
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (f), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
} else {
self.sanctuaryTypeClasses = f();
}
}(function() {
'use strict';
// has :: (String, Object) -> Boolean
var has = function(k, o) {
return Object.prototype.hasOwnProperty.call(o, k);
};
// identity :: a -> a
var identity = function(x) { return x; };
// prepend :: a -> Array a -> Array a
var prepend = function(x) {
return function(xs) {
return [x].concat(xs);
};
};
// type :: Any -> String
var type = function type(x) {
return x != null && type(x['@@type']) === 'String' ?
x['@@type'] :
Object.prototype.toString.call(x).slice('[object '.length, -']'.length);
};
//# TypeClass :: (String, Array TypeClass, a -> Boolean) -> TypeClass
//.
//. The arguments are:
//.
//. - the name of the type class, prefixed by its npm package name;
//. - an array of dependencies; and
//. - a predicate which accepts any JavaScript value and returns `true`
//. if the value satisfies the requirements of the type class; `false`
//. otherwise.
//.
//. Example:
//.
//. ```javascript
//. // hasMethod :: String -> a -> Boolean
//. const hasMethod = name => x => x != null && typeof x[name] == 'function';
//.
//. // Foo :: TypeClass
//. const Foo = Z.TypeClass('my-package/Foo', [], hasMethod('foo'));
//.
//. // Bar :: TypeClass
//. const Bar = Z.TypeClass('my-package/Bar', [Foo], hasMethod('bar'));
//. ```
//.
//. Types whose values have a `foo` method are members of the Foo type class.
//. Members of the Foo type class whose values have a `bar` method are also
//. members of the Bar type class.
//.
//. Each `TypeClass` value has a `test` field: a function which accepts
//. any JavaScript value and returns `true` if the value satisfies the
//. type class's predicate and the predicates of all the type class's
//. dependencies; `false` otherwise.
//.
//. `TypeClass` values may be used with [sanctuary-def][type-classes]
//. to define parametrically polymorphic functions which verify their
//. type-class constraints at run time.
var TypeClass = function(name, dependencies, test) {
return {
'@@type': 'sanctuary-type-classes/TypeClass',
name: name,
test: function(x) {
return dependencies.every(function(d) { return d.test(x); }) &&
test(x);
}
};
};
// data Location = Constructor | Value
// Constructor :: Location
var Constructor = 'Constructor';
// Value :: Location
var Value = 'Value';
// _funcPath :: (Boolean, Array String, a) -> Nullable Function
var _funcPath = function(allowInheritedProps, path, _x) {
var x = _x;
for (var idx = 0; idx < path.length; idx += 1) {
var k = path[idx];
if (x == null || !(allowInheritedProps || has(k, x))) return null;
x = x[k];
}
return typeof x === 'function' ? x : null;
};
// funcPath :: (Array String, a) -> Nullable Function
var funcPath = function(path, x) {
return _funcPath(true, path, x);
};
// implPath :: Array String -> Nullable Function
var implPath = function(path) {
return _funcPath(false, path, implementations);
};
// $ :: (String, Array TypeClass, StrMap (Array Location)) -> TypeClass
var $ = function(_name, dependencies, requirements) {
var getBoundMethod = function(_name) {
return function(x) {
var name = 'fantasy-land/' + _name;
var locations = requirements[_name];
for (var idx = 0; idx < locations.length; idx += 1) {
if (locations[idx] === Constructor) {
var f = funcPath(['constructor', name], x) ||
implPath([type(x), name]);
/* istanbul ignore else */ // Constructor always listed last
if (f) return f;
} else {
var m = funcPath([name], x) ||
implPath([type(x), 'prototype', name]);
if (m) return m.bind(x);
}
}
};
};
var name = 'sanctuary-type-classes/' + _name;
var keys = Object.keys(requirements);
var typeClass = TypeClass(name, dependencies, function(x) {
return keys.every(function(_name) {
return getBoundMethod(_name)(x) != null;
});
});
typeClass.functions = {};
keys.forEach(function(_name) {
var name = 'fantasy-land/' + _name;
if (requirements[_name].indexOf(Constructor) >= 0) {
typeClass.functions[_name] = function(typeRep) {
var m = /function (\w*)/.exec(typeRep);
return m && implPath([m[1], name]) || typeRep[name];
};
}
});
typeClass.methods = {};
keys.forEach(function(_name) {
/* istanbul ignore else */ // Value always listed
if (requirements[_name].indexOf(Value) >= 0) {
typeClass.methods[_name] = getBoundMethod(_name);
}
});
return typeClass;
};
//# Setoid :: TypeClass
//.
//. `TypeClass` value for [Setoid][].
//.
//. ```javascript
//. > Setoid.test(null)
//. true
//. ```
var Setoid = $('Setoid', [], {equals: [Value]});
//# Semigroup :: TypeClass
//.
//. `TypeClass` value for [Semigroup][].
//.
//. ```javascript
//. > Semigroup.test('')
//. true
//.
//. > Semigroup.test(0)
//. false
//. ```
var Semigroup = $('Semigroup', [], {concat: [Value]});
//# Monoid :: TypeClass
//.
//. `TypeClass` value for [Monoid][].
//.
//. ```javascript
//. > Monoid.test('')
//. true
//.
//. > Monoid.test(0)
//. false
//. ```
var Monoid = $('Monoid', [Semigroup], {empty: [Value, Constructor]});
//# Functor :: TypeClass
//.
//. `TypeClass` value for [Functor][].
//.
//. ```javascript
//. > Functor.test([])
//. true
//.
//. > Functor.test('')
//. false
//. ```
var Functor = $('Functor', [], {map: [Value]});
//# Bifunctor :: TypeClass
//.
//. `TypeClass` value for [Bifunctor][].
//.
//. ```javascript
//. > Bifunctor.test(Tuple('foo', 64))
//. true
//.
//. > Bifunctor.test([])
//. false
//. ```
var Bifunctor = $('Bifunctor', [Functor], {bimap: [Value]});
//# Profunctor :: TypeClass
//.
//. `TypeClass` value for [Profunctor][].
//.
//. ```javascript
//. > Profunctor.test(Math.sqrt)
//. true
//.
//. > Profunctor.test([])
//. false
//. ```
var Profunctor = $('Profunctor', [Functor], {promap: [Value]});
//# Apply :: TypeClass
//.
//. `TypeClass` value for [Apply][].
//.
//. ```javascript
//. > Apply.test([])
//. true
//.
//. > Apply.test({})
//. false
//. ```
var Apply = $('Apply', [Functor], {ap: [Value]});
//# Applicative :: TypeClass
//.
//. `TypeClass` value for [Applicative][].
//.
//. ```javascript
//. > Applicative.test([])
//. true
//.
//. > Applicative.test({})
//. false
//. ```
var Applicative = $('Applicative', [Apply], {of: [Value, Constructor]});
//# Chain :: TypeClass
//.
//. `TypeClass` value for [Chain][].
//.
//. ```javascript
//. > Chain.test([])
//. true
//.
//. > Chain.test({})
//. false
//. ```
var Chain = $('Chain', [Apply], {chain: [Value]});
//# ChainRec :: TypeClass
//.
//. `TypeClass` value for [ChainRec][].
//.
//. ```javascript
//. > ChainRec.test([])
//. true
//.
//. > ChainRec.test({})
//. false
//. ```
var ChainRec = $('ChainRec', [Chain], {chainRec: [Value, Constructor]});
//# Monad :: TypeClass
//.
//. `TypeClass` value for [Monad][].
//.
//. ```javascript
//. > Monad.test([])
//. true
//.
//. > Monad.test({})
//. false
//. ```
var Monad = $('Monad', [Applicative, Chain], {});
//# Foldable :: TypeClass
//.
//. `TypeClass` value for [Foldable][].
//.
//. ```javascript
//. > Foldable.test({})
//. true
//.
//. > Foldable.test('')
//. false
//. ```
var Foldable = $('Foldable', [], {reduce: [Value]});
//# Traversable :: TypeClass
//.
//. `TypeClass` value for [Traversable][].
//.
//. ```javascript
//. > Traversable.test([])
//. true
//.
//. > Traversable.test({})
//. false
//. ```
var Traversable = $('Traversable', [Functor, Foldable], {traverse: [Value]});
//# Extend :: TypeClass
//.
//. `TypeClass` value for [Extend][].
//.
//. ```javascript
//. > Extend.test([])
//. true
//.
//. > Extend.test({})
//. false
//. ```
var Extend = $('Extend', [], {extend: [Value]});
//# Comonad :: TypeClass
//.
//. `TypeClass` value for [Comonad][].
//.
//. ```javascript
//. > Comonad.test(Identity(0))
//. true
//.
//. > Comonad.test([])
//. false
//. ```
var Comonad = $('Comonad', [Functor, Extend], {extract: [Value]});
// Null$prototype$toString :: Null ~> () -> String
var Null$prototype$toString = function() {
return 'null';
};
// Null$prototype$equals :: Null ~> Null -> Boolean
var Null$prototype$equals = function(other) {
return true;
};
// Undefined$prototype$toString :: Undefined ~> () -> String
var Undefined$prototype$toString = function() {
return 'undefined';
};
// Undefined$prototype$equals :: Undefined ~> Undefined -> Boolean
var Undefined$prototype$equals = function(other) {
return true;
};
// Boolean$prototype$toString :: Boolean ~> () -> String
var Boolean$prototype$toString = function() {
return typeof this === 'object' ?
'new Boolean(' + toString(this.valueOf()) + ')' :
this.toString();
};
// Boolean$prototype$equals :: Boolean ~> Boolean -> Boolean
var Boolean$prototype$equals = function(other) {
return typeof other === typeof this && other.valueOf() === this.valueOf();
};
// Number$prototype$toString :: Number ~> () -> String
var Number$prototype$toString = function() {
return typeof this === 'object' ?
'new Number(' + toString(this.valueOf()) + ')' :
1 / this === -Infinity ? '-0' : this.toString(10);
};
// Number$prototype$equals :: Number ~> Number -> Boolean
var Number$prototype$equals = function(other) {
return typeof other === 'object' ?
typeof this === 'object' &&
equals(other.valueOf(), this.valueOf()) :
isNaN(other) && isNaN(this) ||
other === this && 1 / other === 1 / this;
};
// Date$prototype$toString :: Date ~> () -> String
var Date$prototype$toString = function() {
var x = isNaN(this.valueOf()) ? NaN : this.toISOString();
return 'new Date(' + toString(x) + ')';
};
// Date$prototype$equals :: Date ~> Date -> Boolean
var Date$prototype$equals = function(other) {
return equals(other.valueOf(), this.valueOf());
};
// RegExp$prototype$equals :: RegExp ~> RegExp -> Boolean
var RegExp$prototype$equals = function(other) {
return other.source === this.source &&
other.global === this.global &&
other.ignoreCase === this.ignoreCase &&
other.multiline === this.multiline &&
other.sticky === this.sticky &&
other.unicode === this.unicode;
};
// String$empty :: () -> String
var String$empty = function() {
return '';
};
// String$prototype$toString :: String ~> () -> String
var String$prototype$toString = function() {
return typeof this === 'object' ?
'new String(' + toString(this.valueOf()) + ')' :
'"' + this.replace(/\\/g, '\\\\')
.replace(/[\b]/g, '\\b') // \b matches word boundary;
.replace(/\f/g, '\\f') // [\b] matches backspace
.replace(/\n/g, '\\n')
.replace(/\r/g, '\\r')
.replace(/\t/g, '\\t')
.replace(/\v/g, '\\v')
.replace(/\0/g, '\\0')
.replace(/"/g, '\\"') + '"';
};
// String$prototype$equals :: String ~> String -> Boolean
var String$prototype$equals = function(other) {
return typeof other === typeof this && other.valueOf() === this.valueOf();
};
// String$prototype$concat :: String ~> String -> String
var String$prototype$concat = function(other) {
return this + other;
};
// Array$empty :: () -> Array a
var Array$empty = function() {
return [];
};
// Array$of :: a -> Array a
var Array$of = function(x) {
return [x];
};
// Array$chainRec :: ((a -> c, b -> c, a) -> Array c, a) -> Array b
var Array$chainRec = function(f, x) {
var next = function(x) { return {value: x, done: false}; };
var done = function(x) { return {value: x, done: true}; };
var $todo = [x];
var $done = [];
while ($todo.length > 0) {
var xs = f(next, done, $todo.shift());
var $more = [];
for (var idx = 0; idx < xs.length; idx += 1) {
(xs[idx].done ? $done : $more).push(xs[idx].value);
}
Array.prototype.unshift.apply($todo, $more);
}
return $done;
};
// Array$prototype$toString :: Array a ~> () -> String
var Array$prototype$toString = function() {
var reprs = this.map(toString);
var keys = Object.keys(this).sort();
for (var idx = 0; idx < keys.length; idx += 1) {
var k = keys[idx];
if (!/^\d+$/.test(k)) {
reprs.push(toString(k) + ': ' + toString(this[k]));
}
}
return '[' + reprs.join(', ') + ']';
};
// Array$prototype$equals :: Array a ~> Array a -> Boolean
var Array$prototype$equals = function(other) {
if (other.length !== this.length) return false;
for (var idx = 0; idx < this.length; idx += 1) {
if (!equals(other[idx], this[idx])) return false;
}
return true;
};
// Array$prototype$concat :: Array a ~> Array a -> Array a
var Array$prototype$concat = function(other) {
return this.concat(other);
};
// Array$prototype$map :: Array a ~> (a -> b) -> Array b
var Array$prototype$map = function(f) {
return this.map(function(x) { return f(x); });
};
// Array$prototype$ap :: Array a ~> Array (a -> b) -> Array b
var Array$prototype$ap = function(fs) {
var result = [];
for (var idx = 0; idx < fs.length; idx += 1) {
for (var idx2 = 0; idx2 < this.length; idx2 += 1) {
result.push(fs[idx](this[idx2]));
}
}
return result;
};
// Array$prototype$chain :: Array a ~> (a -> Array b) -> Array b
var Array$prototype$chain = function(f) {
var result = [];
this.forEach(function(x) { Array.prototype.push.apply(result, f(x)); });
return result;
};
// Array$prototype$reduce :: Array a ~> ((b, a) -> b, b) -> b
var Array$prototype$reduce = function(f, initial) {
return this.reduce(function(acc, x) { return f(acc, x); }, initial);
};
// Array$prototype$traverse :: Applicative f => Array a ~> (a -> f b, c -> f c) -> f (Array b)
var Array$prototype$traverse = function(f, of) {
var applicative = of([]);
for (var idx = this.length - 1; idx >= 0; idx -= 1) {
applicative = ap(map(prepend, f(this[idx])), applicative);
}
return applicative;
};
// Array$prototype$extend :: Array a ~> (Array a -> b) -> Array b
var Array$prototype$extend = function(f) {
return [f(this)];
};
// Arguments$prototype$toString :: Arguments ~> String
var Arguments$prototype$toString = function() {
var args = Array.prototype.map.call(this, toString).join(', ');
return '(function () { return arguments; }(' + args + '))';
};
// Arguments$prototype$equals :: Arguments ~> Arguments -> Boolean
var Arguments$prototype$equals = function(other) {
return Array$prototype$equals.call(this, other);
};
// Error$prototype$toString :: Error ~> () -> String
var Error$prototype$toString = function() {
return 'new ' + this.name + '(' + toString(this.message) + ')';
};
// Error$prototype$equals :: Error ~> Error -> Boolean
var Error$prototype$equals = function(other) {
return equals(other.name, this.name) &&
equals(other.message, this.message);
};
// Object$empty :: () -> StrMap a
var Object$empty = function() {
return {};
};
// Object$prototype$toString :: StrMap a ~> () -> String
var Object$prototype$toString = function() {
var reprs = [];
var keys = Object.keys(this).sort();
for (var idx = 0; idx < keys.length; idx += 1) {
var k = keys[idx];
reprs.push(toString(k) + ': ' + toString(this[k]));
}
return '{' + reprs.join(', ') + '}';
};
// Object$prototype$equals :: StrMap a ~> StrMap a -> Boolean
var Object$prototype$equals = function(other) {
var self = this;
var keys = Object.keys(this).sort();
return equals(Object.keys(other).sort(), keys) &&
keys.every(function(k) { return equals(other[k], self[k]); });
};
// Object$prototype$concat :: StrMap a ~> StrMap a -> StrMap a
var Object$prototype$concat = function(other) {
var result = {};
for (var k in this) result[k] = this[k];
for (k in other) result[k] = other[k];
return result;
};
// Object$prototype$map :: StrMap a ~> (a -> b) -> StrMap b
var Object$prototype$map = function(f) {
var result = {};
for (var k in this) result[k] = f(this[k]);
return result;
};
// Object$prototype$reduce :: StrMap a ~> ((b, a) -> b, b) -> b
var Object$prototype$reduce = function(f, initial) {
var result = initial;
for (var k in this) result = f(result, this[k]);
return result;
};
// Function$of :: b -> (a -> b)
var Function$of = function(x) {
return function(_) { return x; };
};
// Function$prototype$map :: (a -> b) ~> (b -> c) -> (a -> c)
var Function$prototype$map = function(f) {
var functor = this;
return function(x) { return f(functor(x)); };
};
// Function$prototype$promap :: (b -> c) ~> (a -> b, c -> d) -> (a -> d)
var Function$prototype$promap = function(f, g) {
var profunctor = this;
return function(x) { return g(profunctor(f(x))); };
};
// Function$prototype$ap :: (a -> b) ~> (a -> b -> c) -> (a -> c)
var Function$prototype$ap = function(f) {
var apply = this;
return function(x) { return f(x)(apply(x)); };
};
// Function$prototype$chain :: (a -> b) ~> (b -> a -> c) -> (a -> c)
var Function$prototype$chain = function(f) {
var chain = this;
return function(x) { return f(chain(x))(x); };
};
/* eslint-disable key-spacing */
var implementations = {
Null: {
prototype: {
toString: Null$prototype$toString,
'fantasy-land/equals': Null$prototype$equals
}
},
Undefined: {
prototype: {
toString: Undefined$prototype$toString,
'fantasy-land/equals': Undefined$prototype$equals
}
},
Boolean: {
prototype: {
toString: Boolean$prototype$toString,
'fantasy-land/equals': Boolean$prototype$equals
}
},
Number: {
prototype: {
toString: Number$prototype$toString,
'fantasy-land/equals': Number$prototype$equals
}
},
Date: {
prototype: {
toString: Date$prototype$toString,
'fantasy-land/equals': Date$prototype$equals
}
},
RegExp: {
prototype: {
'fantasy-land/equals': RegExp$prototype$equals
}
},
String: {
'fantasy-land/empty': String$empty,
prototype: {
toString: String$prototype$toString,
'fantasy-land/equals': String$prototype$equals,
'fantasy-land/concat': String$prototype$concat
}
},
Array: {
'fantasy-land/empty': Array$empty,
'fantasy-land/of': Array$of,
'fantasy-land/chainRec': Array$chainRec,
prototype: {
toString: Array$prototype$toString,
'fantasy-land/equals': Array$prototype$equals,
'fantasy-land/concat': Array$prototype$concat,
'fantasy-land/map': Array$prototype$map,
'fantasy-land/ap': Array$prototype$ap,
'fantasy-land/chain': Array$prototype$chain,
'fantasy-land/reduce': Array$prototype$reduce,
'fantasy-land/traverse': Array$prototype$traverse,
'fantasy-land/extend': Array$prototype$extend
}
},
Arguments: {
prototype: {
toString: Arguments$prototype$toString,
'fantasy-land/equals': Arguments$prototype$equals
}
},
Error: {
prototype: {
toString: Error$prototype$toString,
'fantasy-land/equals': Error$prototype$equals
}
},
Object: {
'fantasy-land/empty': Object$empty,
prototype: {
toString: Object$prototype$toString,
'fantasy-land/equals': Object$prototype$equals,
'fantasy-land/concat': Object$prototype$concat,
'fantasy-land/map': Object$prototype$map,
'fantasy-land/reduce': Object$prototype$reduce
}
},
Function: {
'fantasy-land/of': Function$of,
prototype: {
'fantasy-land/map': Function$prototype$map,
'fantasy-land/promap': Function$prototype$promap,
'fantasy-land/ap': Function$prototype$ap,
'fantasy-land/chain': Function$prototype$chain
}
}
};
/* eslint-enable key-spacing */
//# toString :: a -> String
//.
//. Returns a useful string representation of its argument.
//.
//. Dispatches to the argument's `toString` method if appropriate.
//.
//. Where practical, `equals(eval(toString(x)), x) = true`.
//.
//. `toString` implementations are provided for the following built-in types:
//. Null, Undefined, Boolean, Number, Date, String, Array, Arguments, Error,
//. and Object.
//.
//. ```javascript
//. > toString(-0)
//. '-0'
//.
//. > toString(['foo', 'bar', 'baz'])
//. '["foo", "bar", "baz"]'
//.
//. > toString({x: 1, y: 2, z: 3})
//. '{"x": 1, "y": 2, "z": 3}'
//.
//. > toString(Cons(1, Cons(2, Cons(3, Nil))))
//. 'Cons(1, Cons(2, Cons(3, Nil)))'
//. ```
var toString = (function() {
// $seen :: Array Any
var $seen = [];
var call = function(method, x) {
$seen.push(x);
try { return method.call(x); } finally { $seen.pop(); }
};
return function toString(x) {
if ($seen.indexOf(x) >= 0) return '<Circular>';
var xType = type(x);
if (xType === 'Object') {
var result;
try { result = call(x.toString, x); } catch (err) {}
if (result != null && result !== '[object Object]') return result;
}
return call(implPath([xType, 'prototype', 'toString']) || x.toString, x);
};
}());
//# equals :: (a, b) -> Boolean
//.
//. Returns `true` if its arguments are of the same type and equal according
//. to the type's [`fantasy-land/equals`][] method; `false` otherwise.
//.
//. `fantasy-land/equals` implementations are provided for the following
//. built-in types: Null, Undefined, Boolean, Number, Date, RegExp, String,
//. Array, Arguments, Error, and Object.
//.
//. ```javascript
//. > equals(0, -0)
//. false
//.
//. > equals(NaN, NaN)
//. true
//.
//. > equals(Cons('foo', Cons('bar', Nil)), Cons('foo', Cons('bar', Nil)))
//. true
//.
//. > equals(Cons('foo', Cons('bar', Nil)), Cons('bar', Cons('foo', Nil)))
//. false
//. ```
var equals = (function() {
// eq :: Setoid a => a -> a -> Boolean
var eq = Setoid.methods.equals;
// $seen :: Array Any
var $seen = [];
// equal :: (a, b) -> Boolean
var equal = function(x, y) {
$seen.push(x, y);
try {
return Setoid.test(x) && Setoid.test(y) && eq(x)(y) && eq(y)(x);
} finally {
$seen.splice(-2, 2);
}
};
return function equals(x, y) {
return Object(x) === Object(y) || type(x) === type(y)
&& $seen.indexOf(x) < 0
&& $seen.indexOf(y) < 0
&& equal(x, y);
};
}());
//# concat :: Semigroup a => (a, a) -> a
//.
//. Function wrapper for [`fantasy-land/concat`][].
//.
//. `fantasy-land/concat` implementations are provided for the following
//. built-in types: String, Array, and Object.
//.
//. ```javascript
//. > concat('abc', 'def')
//. 'abcdef'
//.
//. > concat([1, 2, 3], [4, 5, 6])
//. [1, 2, 3, 4, 5, 6]
//.
//. > concat({x: 1, y: 2}, {y: 3, z: 4})
//. {x: 1, y: 3, z: 4}
//.
//. > concat(Cons('foo', Cons('bar', Cons('baz', Nil))), Cons('quux', Nil))
//. Cons('foo', Cons('bar', Cons('baz', Cons('quux', Nil))))
//. ```
var concat = function concat(x, y) {
return Semigroup.methods.concat(x)(y);
};
//# empty :: Monoid m => TypeRep m -> m
//.
//. Function wrapper for [`fantasy-land/empty`][].
//.
//. `fantasy-land/empty` implementations are provided for the following
//. built-in types: String, Array, and Object.
//.
//. ```javascript
//. > empty(String)
//. ''
//.
//. > empty(Array)
//. []
//.
//. > empty(Object)
//. {}
//.
//. > empty(List)
//. Nil
//. ```
var empty = function empty(typeRep) {
return Monoid.functions.empty(typeRep)();
};
//# map :: Functor f => (a -> b, f a) -> f b
//.
//. Function wrapper for [`fantasy-land/map`][].
//.
//. `fantasy-land/map` implementations are provided for the following
//. built-in types: Array, Object, and Function.
//.
//. ```javascript
//. > map(Math.sqrt, [1, 4, 9])
//. [1, 2, 3]
//.
//. > map(Math.sqrt, {x: 1, y: 4, z: 9})
//. {x: 1, y: 2, z: 3}
//.
//. > map(Math.sqrt, s => s.length)('Sanctuary')
//. 3
//.
//. > map(Math.sqrt, Tuple('foo', 64))
//. Tuple('foo', 8)
//.
//. > map(Math.sqrt, Nil)
//. Nil
//.
//. > map(Math.sqrt, Cons(1, Cons(4, Cons(9, Nil))))
//. Cons(1, Cons(2, Cons(3, Nil)))
//. ```
var map = function map(f, functor) {
return Functor.methods.map(functor)(f);
};
//# bimap :: Bifunctor f => (a -> b, c -> d, f a c) -> f b d
//.
//. Function wrapper for [`fantasy-land/bimap`][].
//.
//. ```javascript
//. > bimap(s => s.toUpperCase(), Math.sqrt, Tuple('foo', 64))
//. Tuple('FOO', 8)
//. ```
var bimap = function bimap(f, g, bifunctor) {
return Bifunctor.methods.bimap(bifunctor)(f, g);
};
//# promap :: Profunctor p => (a -> b, c -> d, p b c) -> p a d
//.
//. Function wrapper for [`fantasy-land/promap`][].
//.
//. `fantasy-land/promap` implementations are provided for the following
//. built-in types: Function.
//.
//. ```javascript
//. > promap(Math.abs, x => x + 1, Math.sqrt)(-100)
//. 11
//. ```
var promap = function promap(f, g, profunctor) {
return Profunctor.methods.promap(profunctor)(f, g);
};
//# ap :: Apply f => (f (a -> b), f a) -> f b
//.
//. Function wrapper for [`fantasy-land/ap`][].
//.
//. `fantasy-land/ap` implementations are provided for the following
//. built-in types: Array and Function.
//.
//. ```javascript
//. > ap([Math.sqrt, x => x * x], [1, 4, 9, 16, 25])
//. [1, 2, 3, 4, 5, 1, 16, 81, 256, 625]
//.
//. > ap(s => n => s.slice(0, n), s => Math.ceil(s.length / 2))('Haskell')
//. 'Hask'
//.
//. > ap(Identity(Math.sqrt), Identity(64))
//. Identity(8)
//.
//. > ap(Cons(Math.sqrt, Cons(x => x * x, Nil)), Cons(16, Cons(100, Nil)))
//. Cons(4, Cons(10, Cons(256, Cons(10000, Nil))))
//. ```
var ap = function ap(applyF, applyX) {
return Apply.methods.ap(applyX)(applyF);
};
//# lift2 :: Apply f => (a -> b -> c, f a, f b) -> f c
//.
//. Lifts `a -> b -> c` to `Apply f => f a -> f b -> f c` and returns the
//. result of applying this to the given arguments.
//.
//. This function is derived from [`map`](#map) and [`ap`](#ap).
//.
//. See also [`lift3`](#lift3).
//.
//. ```javascript
//. > lift2(x => y => Math.pow(x, y), [10], [1, 2, 3])
//. [10, 100, 1000]
//.
//. > lift2(x => y => Math.pow(x, y), Identity(10), Identity(3))
//. Identity(1000)
//. ```
var lift2 = function lift2(f, x, y) {
return ap(map(f, x), y);
};
//# lift3 :: Apply f => (a -> b -> c -> d, f a, f b, f c) -> f d
//.
//. Lifts `a -> b -> c -> d` to `Apply f => f a -> f b -> f c -> f d` and
//. returns the result of applying this to the given arguments.
//.
//. This function is derived from [`map`](#map) and [`ap`](#ap).
//.
//. See also [`lift2`](#lift2).
//.
//. ```javascript
//. > lift3(x => y => z => x + z + y, ['<'], ['>'], ['foo', 'bar', 'baz'])
//. ['<foo>', '<bar>', '<baz>']
//.
//. > lift3(x => y => z => x + z + y, Identity('<'), Identity('>'), Identity('baz'))
//. Identity('<baz>')
//. ```
var lift3 = function lift3(f, x, y, z) {
return ap(ap(map(f, x), y), z);
};
//# of :: Applicative f => (TypeRep f, a) -> f a
//.
//. Function wrapper for [`fantasy-land/of`][].
//.
//. `fantasy-land/of` implementations are provided for the following
//. built-in types: Array and Function.
//.
//. ```javascript
//. > of(Array, 42)
//. [42]
//.
//. > of(Function, 42)(null)
//. 42
//.
//. > of(List, 42)
//. Cons(42, Nil)
//. ```
var of = function of(typeRep, x) {
return Applicative.functions.of(typeRep)(x);
};
//# chain :: Chain m => (a -> m b, m a) -> m b
//.
//. Function wrapper for [`fantasy-land/chain`][].
//.
//. `fantasy-land/chain` implementations are provided for the following
//. built-in types: Array and Function.
//.
//. ```javascript
//. > chain(x => [x, x], [1, 2, 3])
//. [1, 1, 2, 2, 3, 3]
//.
//. > chain(x => x % 2 == 1 ? of(List, x) : Nil, Cons(1, Cons(2, Cons(3, Nil))))
//. Cons(1, Cons(3, Nil))
//.
//. > chain(n => s => s.slice(0, n), s => Math.ceil(s.length / 2))('Haskell')
//. 'Hask'
//. ```
var chain = function chain(f, chain) {
return Chain.methods.chain(chain)(f);
};
//# chainRec :: ChainRec m => (TypeRep m, (a -> c, b -> c, a) -> m c, a) -> m b
//.
//. Function wrapper for [`fantasy-land/chainRec`][].
//.
//. `fantasy-land/chainRec` implementations are provided for the following
//. built-in types: Array.
//.
//. ```javascript
//. > chainRec(
//. . Array,
//. . (next, done, s) => s.length == 2 ? [s + '!', s + '?'].map(done)
//. . : [s + 'o', s + 'n'].map(next),
//. . ''
//. . )
//. ['oo!', 'oo?', 'on!', 'on?', 'no!', 'no?', 'nn!', 'nn?']
//. ```
var chainRec = function chainRec(typeRep, f, x) {
return ChainRec.functions.chainRec(typeRep)(f, x);
};
//# filter :: (Applicative f, Foldable f, Monoid (f a)) => (a -> Boolean, f a) -> f a
//.
//. Filters its second argument in accordance with the given predicate.
//.
//. This function is derived from [`empty`](#empty), [`of`](#of), and
//. [`reduce`](#reduce).
//.
//. See also [`filterM`](#filterM).
//.
//. ```javascript
//. > filter(x => x % 2 == 1, [1, 2, 3])
//. [1, 3]
//.
//. > filter(x => x % 2 == 1, Cons(1, Cons(2, Cons(3, Nil))))
//. Cons(1, Cons(3, Nil))
//. ```
var filter = function filter(pred, m) {
var M = m.constructor;
return reduce(function(m, x) { return pred(x) ? concat(m, of(M, x)) : m; },
empty(M),
m);
};
//# filterM :: (Monad m, Monoid (m a)) => (a -> Boolean, m a) -> m a
//.
//. Filters its second argument in accordance with the given predicate.
//.
//. This function is derived from [`empty`](#empty), [`of`](#of), and
//. [`chain`](#chain).
//.
//. See also [`filter`](#filter).
//.
//. ```javascript
//. > filterM(x => x % 2 == 1, [1, 2, 3])
//. [1, 3]
//.
//. > filterM(x => x % 2 == 1, Cons(1, Cons(2, Cons(3, Nil))))
//. Cons(1, Cons(3, Nil))
//. ```
var filterM = function filterM(pred, m) {
var M = m.constructor;
var e = empty(M);
return chain(function(x) { return pred(x) ? of(M, x) : e; }, m);
};
//# reduce :: Foldable f => ((b, a) -> b, b, f a) -> b
//.
//. Function wrapper for [`fantasy-land/reduce`][].
//.
//. `fantasy-land/reduce` implementations are provided for the following
//. built-in types: Array and Object.
//.
//. ```javascript
//. > reduce((xs, x) => [x].concat(xs), [], [1, 2, 3])
//. [3, 2, 1]
//.
//. > reduce(concat, '', Cons('foo', Cons('bar', Cons('baz', Nil))))
//. 'foobarbaz'
//. ```
var reduce = function reduce(f, x, foldable) {
return Foldable.methods.reduce(foldable)(f, x);
};
//# traverse :: (Applicative f, Traversable t) => (a -> f a, b -> f c, t b) -> f (t c)
//.
//. Function wrapper for [`fantasy-land/traverse`][].
//.
//. `fantasy-land/traverse` implementations are provided for the following
//. built-in types: Array.
//.
//. See also [`sequence`](#sequence).
//.
//. ```javascript
//. > traverse(x => [x], x => x, [[1, 2, 3], [4, 5]])
//. [[1, 4], [1, 5], [2, 4], [2, 5], [3, 4], [3, 5]]
//.
//. > traverse(Identity, x => Identity(x + 1), [1, 2, 3])
//. Identity([2, 3, 4])
//. ```
var traverse = function traverse(of, f, traversable) {
return Traversable.methods.traverse(traversable)(f, of);
};
//# sequence :: (Applicative f, Traversable t) => (a -> f a, t (f b)) -> f (t b)
//.
//. Inverts the given `t (f b)` to produce an `f (t b)`.
//.
//. This function is derived from [`traverse`](#traverse).
//.
//. ```javascript
//. > sequence(x => [x], Identity([1, 2, 3]))
//. [Identity(1), Identity(2), Identity(3)]
//.
//. > sequence(Identity, [Identity(1), Identity(2), Identity(3)])
//. Identity([1, 2, 3])
//. ```
var sequence = function sequence(of, traversable) {
return traverse(of, identity, traversable);
};
//# extend :: Extend w => (w a -> b, w a) -> w b
//.
//. Function wrapper for [`fantasy-land/extend`][].
//.
//. `fantasy-land/extend` implementations are provided for the following
//. built-in types: Array.
//.
//. ```javascript
//. > extend(xs => xs.length, ['foo', 'bar', 'baz', 'quux'])
//. [4]
//. ```
var extend = function extend(f, extend) {
return Extend.methods.extend(extend)(f);
};
//# extract :: Comonad w => w a -> a
//.
//. Function wrapper for [`fantasy-land/extract`][].
//.
//. ```javascript
//. > extract(Identity(42))
//. 42
//. ```
var extract = function extract(comonad) {
return Comonad.methods.extract(comonad)();
};
return {
TypeClass: TypeClass,
Setoid: Setoid,
Semigroup: Semigroup,
Monoid: Monoid,
Functor: Functor,
Bifunctor: Bifunctor,
Profunctor: Profunctor,
Apply: Apply,
Applicative: Applicative,
Chain: Chain,
ChainRec: ChainRec,
Monad: Monad,
Foldable: Foldable,
Traversable: Traversable,
Extend: Extend,
Comonad: Comonad,
toString: toString,
equals: equals,
concat: concat,
empty: empty,
map: map,
bimap: bimap,
promap: promap,
ap: ap,
lift2: lift2,
lift3: lift3,
of: of,
chain: chain,
chainRec: chainRec,
filter: filter,
filterM: filterM,
reduce: reduce,
traverse: traverse,
sequence: sequence,
extend: extend,
extract: extract
};
}));
//. [Applicative]: https://github.com/fantasyland/fantasy-land#applicative
//. [Apply]: https://github.com/fantasyland/fantasy-land#apply
//. [Bifunctor]: https://github.com/fantasyland/fantasy-land#bifunctor
//. [Chain]: https://github.com/fantasyland/fantasy-land#chain
//. [ChainRec]: https://github.com/fantasyland/fantasy-land#chainrec
//. [Comonad]: https://github.com/fantasyland/fantasy-land#comonad
//. [Extend]: https://github.com/fantasyland/fantasy-land#extend
//. [FL]: https://github.com/fantasyland/fantasy-land
//. [Foldable]: https://github.com/fantasyland/fantasy-land#foldable
//. [Functor]: https://github.com/fantasyland/fantasy-land#functor
//. [Monad]: https://github.com/fantasyland/fantasy-land#monad
//. [Monoid]: https://github.com/fantasyland/fantasy-land#monoid
//. [Profunctor]: https://github.com/fantasyland/fantasy-land#profunctor
//. [Semigroup]: https://github.com/fantasyland/fantasy-land#semigroup
//. [Setoid]: https://github.com/fantasyland/fantasy-land#setoid
//. [Traversable]: https://github.com/fantasyland/fantasy-land#traversable
//. [`fantasy-land/ap`]: https://github.com/fantasyland/fantasy-land#ap-method
//. [`fantasy-land/bimap`]: https://github.com/fantasyland/fantasy-land#bimap-method
//. [`fantasy-land/chain`]: https://github.com/fantasyland/fantasy-land#chain-method
//. [`fantasy-land/chainRec`]: https://github.com/fantasyland/fantasy-land#chainrec-method
//. [`fantasy-land/concat`]: https://github.com/fantasyland/fantasy-land#concat-method
//. [`fantasy-land/empty`]: https://github.com/fantasyland/fantasy-land#empty-method
//. [`fantasy-land/equals`]: https://github.com/fantasyland/fantasy-land#equals-method
//. [`fantasy-land/extend`]: https://github.com/fantasyland/fantasy-land#extend-method
//. [`fantasy-land/extract`]: https://github.com/fantasyland/fantasy-land#extract-method
//. [`fantasy-land/map`]: https://github.com/fantasyland/fantasy-land#map-method
//. [`fantasy-land/of`]: https://github.com/fantasyland/fantasy-land#of-method
//. [`fantasy-land/promap`]: