UNPKG

typecat

Version:

A tiny functional programming library for TypeScript that provides Option (Some/None) and Either(Left/Right) with functor map, applicative map and monad flatmap

267 lines 10.3 kB
"use strict"; var __values = (this && this.__values) || function (o) { var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; if (m) return m.call(o); return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; }; Object.defineProperty(exports, "__esModule", { value: true }); var index_1 = require("./index"); describe('id', function () { test('for any value, id returns exactly the same value', function () { var Person = (function () { function Person(name, age) { this._name = name; this._age = age; } Object.defineProperty(Person.prototype, "name", { get: function () { return this._name; }, enumerable: true, configurable: true }); Object.defineProperty(Person.prototype, "age", { get: function () { return this._age; }, enumerable: true, configurable: true }); return Person; }()); var jack = new Person('Jace London', 35); var plus = function (a) { return a + 1; }; expect(index_1.id(0)).toBe(0); expect(index_1.id(undefined)).toBeUndefined(); expect(index_1.id(null)).toBeNull(); expect(index_1.id(plus)).toBe(plus); expect(index_1.id(jack)).toBe(jack); }); }); describe('Option functor', function () { test('Law: Some.fmap(id) === id(Some)', function () { var a = new index_1.Some(33); expect(a.fmap(index_1.id)).toEqual(index_1.id(a)); }); test('Law None.fmap(id) = id(None)', function () { var a = new index_1.None(); expect(a.fmap(index_1.id)).toEqual(index_1.id(a)); }); test(' Some(a).fmap(f) === Some(f(a))', function () { var i = 5; var a = new index_1.Some(i); var f = function (a) { return a + 2; }; expect(a.fmap(f)).toEqual(new index_1.Some(f(i))); }); test(' None.fmap(f) = None', function () { var a = new index_1.None(); var f = function (a) { return a + 2; }; expect(a.fmap(f)).toEqual(new index_1.None()); }); }); describe('Option applicative', function () { test('Law Some(id).applyMap( Some(a)) = Some(id(a))', function () { var i = 33; var a = new index_1.Some(i); expect(new index_1.Some(index_1.id).applyMap(a)).toEqual(new index_1.Some(index_1.id(i))); }); test('Some(f).applyMap( Some(a)) = (Some(f(a))', function () { var i = 33; var a = new index_1.Some(i); var f = function (a) { return a + 2; }; expect(new index_1.Some(f).applyMap(a)).toEqual(new index_1.Some(f(i))); }); test('Some(f(a,b)).applyMap( Some(a)).applyMap(Some(b)) = (Some(f(a,b))', function () { var i = 3; var j = 4; var a = new index_1.Some(i); var b = new index_1.Some(j); var f = function (a) { return function (b) { return a * 2 + b; }; }; expect(new index_1.Some(f).applyMap(a).applyMap(b)).toEqual(new index_1.Some(f(i)(j))); }); }); describe('Option iterator', function () { test('for iterator of Some(a) equals a ', function () { var e_1, _a; var i = 33; var a = new index_1.Some(i); try { for (var a_1 = __values(a), a_1_1 = a_1.next(); !a_1_1.done; a_1_1 = a_1.next()) { var b = a_1_1.value; expect(b).toEqual(i); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (a_1_1 && !a_1_1.done && (_a = a_1.return)) _a.call(a_1); } finally { if (e_1) throw e_1.error; } } }); test('for iterator of None, iterator return done immediately ', function () { var e_2, _a; var a = new index_1.None(); var w = 0; try { for (var a_2 = __values(a), a_2_1 = a_2.next(); !a_2_1.done; a_2_1 = a_2.next()) { var b = a_2_1.value; w = 1; } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (a_2_1 && !a_2_1.done && (_a = a_2.return)) _a.call(a_2); } finally { if (e_2) throw e_2.error; } } expect(w).not.toBe(1); }); }); describe('Option monad', function () { test('Some(a).flatMap(f: (a)=>Some(b)) === Some(b) ', function () { var i = 33; var a = new index_1.Some(i); var f = function (a) { return new index_1.Some(typeof a); }; expect(a.flatMap(f)).toEqual(f(i)); }); test('Some(a).flatMap(f: (a)=> None) === None ', function () { var a = new index_1.None(); var f = function (a) { return new index_1.Some(typeof a); }; expect(a.flatMap(f)).toEqual(new index_1.None()); }); test('None.flatMap(f: (a)=>b) === None ', function () { var a = new index_1.None(); var f = function (a) { return new index_1.Some(typeof a); }; expect(a.flatMap(f)).toEqual(new index_1.None()); }); }); describe('Either functor', function () { test('Law: Right.fmap(id) === id(Right)', function () { var a = new index_1.Right(33); expect(a.fmap(index_1.id)).toEqual(index_1.id(a)); }); test('Law Left.fmap(id) = id(Left)', function () { var a = new index_1.Left(44); expect(a.fmap(index_1.id)).toEqual(index_1.id(a)); }); test(' Right(a).fmap(f) === Right(f(a))', function () { var i = 5; var a = new index_1.Right(i); var f = function (a) { return a + 2; }; expect(a.fmap(f)).toEqual(new index_1.Right(f(i))); }); test(' Left(a).fmap(f) === Left(a)', function () { var i = 5; var a = new index_1.Left(i); var f = function (a) { return a + 2; }; expect(a.fmap(f)).toEqual(new index_1.Left(i)); }); }); describe('Either applicative', function () { test('Law: Right.applyMap(Right(id)) === id(Right)', function () { var a = new index_1.Right(33); var rid = new index_1.Right(index_1.id); expect(rid.applyMap(a)).toEqual(index_1.id(a)); }); test('Law: Left.applyMap(Right(id)) === id(Left)', function () { var a = new index_1.Right(33); var lid = new index_1.Left(index_1.id); expect(lid.applyMap(a)).toEqual(index_1.id(new index_1.Left(index_1.id))); }); test('Law: Right.applyMap(Left) === Left', function () { var a = new index_1.Right(function (a, b) { return a + b; }); var b = new index_1.Left(45); expect(a.applyMap(b)).toEqual(b); }); test('Law: Lefta.applyMap(Leftb) === Leftb', function () { var a = new index_1.Left(function (a, b) { return a + b; }); var b = new index_1.Left(45); expect(a.applyMap(b)).toEqual(b); }); }); describe('Either monad', function () { test('Law: Right.flatMap( f:(a) => Right(b) === Right(b)', function () { var i = 33; var a = new index_1.Right(33); var f = function (a) { return new index_1.Right(a.toString()); }; expect(a.flatMap(f)).toEqual(new index_1.Right(i.toString())); }); test('Law: Left.flatMap( f:(a) => Right(b) === Left', function () { var i = 33; var a = new index_1.Left(i); var f = function (a) { return new index_1.Right(a.toString()); }; expect(a.flatMap(f)).toEqual(new index_1.Left(i)); }); test('Law: Right.flatMap( f:(a) => Left(b) === Left(b)', function () { var i = 33; var a = new index_1.Right(33); var f = function (a) { return new index_1.Left(a * 2); }; expect(a.flatMap(f)).toEqual(new index_1.Left(i * 2)); }); test('Law: Left.flatMap( f:(a) => Left(b) === Left', function () { var i = 33; var a = new index_1.Left(i); var f = function (a) { return new index_1.Left(a.toString()); }; expect(a.flatMap(f)).toEqual(new index_1.Left(i.toString())); }); }); describe('Extra None test cases ', function () { var e_3, _a; var option = new index_1.Some(3).fmap(function (i) { return i * 2; }); console.log(option); try { for (var option_1 = __values(option), option_1_1 = option_1.next(); !option_1_1.done; option_1_1 = option_1.next()) { var i = option_1_1.value; console.log(i); } } catch (e_3_1) { e_3 = { error: e_3_1 }; } finally { try { if (option_1_1 && !option_1_1.done && (_a = option_1.return)) _a.call(option_1); } finally { if (e_3) throw e_3.error; } } var failed = new index_1.Some(0) .flatMap(function (i) { return (i === 0 ? new index_1.None() : new index_1.Some(1 / i)); }) .fmap(function (w) { return "inverse is " + w; }); console.log(failed); var succeeded = new index_1.Some(10) .flatMap(function (i) { return (i === 0 ? new index_1.None() : new index_1.Some(1 / i)); }) .fmap(function (w) { return "inverse is " + w; }); console.log(succeeded); var either = new index_1.Right(25) .fmap(function (i) { return (i > 20 ? true : false); }) .flatMap(function (t) { return (t ? new index_1.Right('Ok') : new index_1.Left('Fail')); }); console.log(either); console.log(either.getOrElse('ww')); var triplePlusF = function (a) { return function (b) { return function (c) { return a + b + c; }; }; }; var triplePlus = new index_1.Some(triplePlusF); var a = new index_1.Some(2); var b = new index_1.Some(3); var c = new index_1.Some(4); var d = new index_1.None(); var plusedA = triplePlus .applyMap(a) .applyMap(b) .applyMap(c); console.log(plusedA); var ra = plusedA.get(); var plusedB = triplePlus .applyMap(a) .applyMap(b) .applyMap(d); var rb = plusedB.get(); var rc = plusedB.getOrElse(0); console.log(ra); console.log(rb); console.log(rc); }); //# sourceMappingURL=index.test.js.map