diff --git a/package.json b/package.json
index 5321312..2d90d4c 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "teep",
"description": "A JavaScript library for functional programming.",
- "version": "1.0.0",
+ "version": "1.1.0",
"homepage": "https://github.com/earldouglas/teep",
"author": {
"name": "James Earl Douglas",
diff --git a/src/teep.ts b/src/teep.ts
index 5610470..9e377f3 100644
--- a/src/teep.ts
+++ b/src/teep.ts
@@ -26,7 +26,7 @@ module edc {
put: (A, B) => void;
}
- class DumbCache implements Cache {
+ class DumbCache {
cache = {};
get = (k) => { return this.cache[k]; };
put = (k,v) => { this.cache[k] = v; };
@@ -78,7 +78,12 @@ module edc {
},
};
- export interface Option {
+ export interface Monad {
+ map: (f: (A) => B) => Monad;
+ flatMap: (f: (A) => Monad) => Monad;
+ }
+
+ export interface Option extends Monad {
empty : boolean;
map : (f: (A) => B) => Option;
flatMap : (f: (A) => Option) => Option;
@@ -115,7 +120,7 @@ module edc {
}
}
- export interface Validation {
+ export interface Validation extends Monad {
valid : boolean;
map : (f: (A) => B) => Validation;
flatMap : (f: (A) => Validation) => Validation;
@@ -151,7 +156,7 @@ module edc {
invalid: (errors: Array) => { return new Invalid(errors); },
};
- export interface List {
+ export interface List extends Monad {
length : number;
map : (f: (A) => B) => List;
flatMap : (f: (A) => List) => List;
@@ -273,15 +278,38 @@ module edc {
var future = (f: (A) => any) => { return new Future(f); }
+ class ReaderT {
+ f: (A) => Monad;
+ constructor(f: (A) => Monad) {
+ this.f = f;
+ }
+ apply(a: A): Monad {
+ return this.f(a);
+ };
+ map(g: (B) => C): ReaderT {
+ return new ReaderT((a) => {
+ return this.f(a).map(g);
+ });
+ };
+ flatMap(g: (B) => ReaderT): ReaderT {
+ return new ReaderT((a) => {
+ return this.f(a).map(g).flatMap((r) => { return r.apply(a); });
+ });
+ };
+ }
+
+ var readerT = (f: (A) => Monad) => { return new ReaderT(f); }
+
export var teep = {
- array: array,
- fn: fn,
- option: option,
+ array: array,
+ fn: fn,
+ option: option,
validation: validation,
- list: list,
- promise: promise,
- reader: reader,
- future: future,
+ list: list,
+ promise: promise,
+ reader: reader,
+ future: future,
+ readerT: readerT,
};
var setExports = function () {
@@ -296,4 +324,3 @@ module edc {
!exports || setExports();
}
-
diff --git a/teep.js b/teep.js
index 72daa0a..0cb8658 100644
--- a/teep.js
+++ b/teep.js
@@ -253,6 +253,31 @@ var edc;
return Future;
})();
var future = function (f) { return new Future(f); };
+ var ReaderT = (function () {
+ function ReaderT(f) {
+ this.f = f;
+ }
+ ReaderT.prototype.apply = function (a) {
+ return this.f(a);
+ };
+ ;
+ ReaderT.prototype.map = function (g) {
+ var _this = this;
+ return new ReaderT(function (a) {
+ return _this.f(a).map(g);
+ });
+ };
+ ;
+ ReaderT.prototype.flatMap = function (g) {
+ var _this = this;
+ return new ReaderT(function (a) {
+ return _this.f(a).map(g).flatMap(function (r) { return r.apply(a); });
+ });
+ };
+ ;
+ return ReaderT;
+ })();
+ var readerT = function (f) { return new ReaderT(f); };
edc.teep = {
array: array,
fn: fn,
@@ -261,7 +286,8 @@ var edc;
list: list,
promise: promise,
reader: reader,
- future: future
+ future: future,
+ readerT: readerT
};
var setExports = function () {
for (var i in edc.teep) {
diff --git a/test/examples.js b/test/examples.js
index 72a68d1..65d176a 100644
--- a/test/examples.js
+++ b/test/examples.js
@@ -288,7 +288,6 @@ describe('examples', function () {
});
-
describe('future', function () {
var async = function(x) {
return function (k) {
@@ -337,4 +336,50 @@ describe('examples', function () {
});
+ describe('readerT', function () {
+
+ var db = {
+ answer: 42,
+ };
+
+ var getAnswer = function (db) {
+ return teep.future(function (k) {
+ return k(db.answer);
+ });
+ };
+
+ function addToAnswer(x) {
+ return teep.readerT(function (db) {
+ return teep.future(function (k) {
+ return k(db.answer + x);
+ });
+ });
+ };
+
+ function verify(x, done) {
+ return function (y) {
+ if (x === y) {
+ done();
+ }
+ };
+ };
+
+ it('apply', function (done) {
+ teep.readerT(getAnswer).apply(db).apply(verify(42, done));
+ });
+
+ it('map', function (done) {
+ teep.readerT(getAnswer).map(function (x) {
+ return x + 1;
+ }).apply(db).apply(verify(43, done));
+ });
+
+ it('flatMap', function (done) {
+ teep.readerT(getAnswer).flatMap(function (x) {
+ return addToAnswer(x + 1);
+ }).apply(db).apply(verify(85, done));
+ });
+
+ });
+
});