UNPKG

@safareli/free

Version:

Combination of a free applicative functor and free monad

1,629 lines (1,490 loc) 51.8 kB
(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`]: