Repository: gcanti/fp-ts
Pull request #448 (2018-05-21 10:31:44)

refactor: move ReaderTaskEither from examples into src
see https://github.com/gcanti/fp-ts/issues/446


Patch:
diff --git a/examples/ReaderTaskEither.ts b/src/ReaderTaskEither.ts
similarity index 87%
rename from examples/ReaderTaskEither.ts
rename to src/ReaderTaskEither.ts
index 9833139a..54092cd3 100644
--- a/examples/ReaderTaskEither.ts
+++ b/src/ReaderTaskEither.ts
@@ -1,14 +1,14 @@
-import { Either } from '../src/Either'
-import { Monad3 } from '../src/Monad'
-import { Reader } from '../src/Reader'
-import * as readerT from '../src/ReaderT'
-import { Task } from '../src/Task'
-import * as taskEither from '../src/TaskEither'
-import { TaskEither } from '../src/TaskEither'
+import { Either } from './Either'
+import { Monad3 } from './Monad'
+import { Reader } from './Reader'
+import * as readerT from './ReaderT'
+import { Task } from './Task'
+import * as taskEither from './TaskEither'
+import TaskEither = taskEither.TaskEither
 
 const readerTTaskEither = readerT.getReaderT(taskEither.taskEither)
 
-declare module '../src/HKT' {
+declare module './HKT' {
   interface URI2HKT3<U, L, A> {
     ReaderTaskEither: ReaderTaskEither<U, L, A>
   }
@@ -27,9 +27,6 @@ export class ReaderTaskEither<E, L, A> {
   map<B>(f: (a: A) => B): ReaderTaskEither<E, L, B> {
     return new ReaderTaskEither(readerTTaskEither.map(f, this.run))
   }
-  of<E, B>(b: B): ReaderTaskEither<E, L, B> {
-    return of(b)
-  }
   ap<B>(fab: ReaderTaskEither<E, L, (a: A) => B>): ReaderTaskEither<E, L, B> {
     return new ReaderTaskEither(readerTTaskEither.ap(fab.run, this.run))
   }
@@ -64,7 +61,7 @@ const chain = <E, L, A, B>(
 }
 
 const readerTask = readerT.ask(taskEither.taskEither)
-export const ask = <E, L>(e: E): ReaderTaskEither<E, L, E> => {
+export const ask = <E, L>(): ReaderTaskEither<E, L, E> => {
   return new ReaderTaskEither(readerTask())
 }
 
diff --git a/src/index.ts b/src/index.ts
index 09565804..c0287155 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -106,6 +106,8 @@ import * as reader from './Reader'
 export { reader }
 import * as readerT from './ReaderT'
 export { readerT }
+import * as readerTaskEither from './ReaderTaskEither'
+export { readerTaskEither }
 import * as ring from './Ring'
 export { ring }
 import * as semigroup from './Semigroup'
diff --git a/typings-checker/index.ts b/typings-checker/index.ts
index c5a9c9cc..d135fcfe 100644
--- a/typings-checker/index.ts
+++ b/typings-checker/index.ts
@@ -1,4 +1,4 @@
-import { ReaderTaskEither, readerTaskEither } from '../examples/ReaderTaskEither'
+import { ReaderTaskEither, readerTaskEither } from '../src/ReaderTaskEither'
 import { getApplicativeComposition } from '../src/Applicative'
 import { liftA2 } from '../src/Apply'
 import { array } from '../src/Array'


Test patch:
diff --git a/test/ReaderTaskEither.ts b/test/ReaderTaskEither.ts
new file mode 100644
index 00000000..4f74c4a4
--- /dev/null
+++ b/test/ReaderTaskEither.ts
@@ -0,0 +1,180 @@
+import * as assert from 'assert'
+import {
+  readerTaskEither,
+  fromTaskEither,
+  left,
+  right,
+  fromTask,
+  fromEither,
+  fromReader,
+  tryCatch,
+  ask,
+  asks,
+  local,
+  ReaderTaskEither
+} from '../src/ReaderTaskEither'
+import { left as eitherLeft, right as eitherRight, either } from '../src/Either'
+import { fromLeft, taskEither } from '../src/TaskEither'
+import { task } from '../src/Task'
+import { reader } from '../src/Reader'
+
+describe('ReaderTaskEither', () => {
+  it('ap', () => {
+    const double = (n: number): number => n * 2
+    const fab = readerTaskEither.of(double)
+    const fa = readerTaskEither.of(1)
+    return Promise.all([
+      fa
+        .ap(fab)
+        .run({})
+        .run(),
+      fab
+        .ap_(fa)
+        .run({})
+        .run(),
+      readerTaskEither
+        .ap(fab, fa)
+        .run({})
+        .run()
+    ]).then(([e1, e2, e3]) => {
+      assert.deepEqual(e1, eitherRight(2))
+      assert.deepEqual(e1, e2)
+      assert.deepEqual(e1, e3)
+    })
+  })
+
+  it('map', () => {
+    const double = (n: number): number => n * 2
+    return readerTaskEither
+      .map(readerTaskEither.of(1), double)
+      .run({})
+      .run()
+      .then(e => {
+        assert.deepEqual(e, eitherRight(2))
+      })
+  })
+
+  it('chain', () => {
+    const rte1 = readerTaskEither.chain(
+      readerTaskEither.of<{}, string, string>('foo'),
+      a =>
+        a.length > 2
+          ? readerTaskEither.of<{}, string, number>(a.length)
+          : fromTaskEither(fromLeft<string, number>('foo'))
+    )
+    const rte2 = readerTaskEither.chain(
+      readerTaskEither.of<{}, string, string>('a'),
+      a =>
+        a.length > 2
+          ? readerTaskEither.of<{}, string, number>(a.length)
+          : fromTaskEither(fromLeft<string, number>('foo'))
+    )
+    return Promise.all([rte1.run({}).run(), rte2.run({}).run()]).then(([e1, e2]) => {
+      assert.deepEqual(e1, eitherRight(3))
+      assert.deepEqual(e2, eitherLeft('foo'))
+    })
+  })
+
+  it('of', () => {
+    return readerTaskEither
+      .of(1)
+      .run({})
+      .run()
+      .then(e => assert.deepEqual(e, eitherRight(1)))
+  })
+
+  it('ask', () => {
+    const x = ask<number, {}>()
+
+    return x
+      .run(1)
+      .run()
+      .then(e => assert.deepEqual(e, eitherRight(1)))
+  })
+
+  it('asks', () => {
+    const x = asks((s: string) => s.length)
+
+    return x
+      .run('foo')
+      .run()
+      .then(e => assert.deepEqual(e, eitherRight(3)))
+  })
+
+  it('local', () => {
+    const double = (n: number): number => n * 2
+    const doubleLocal = local<number>(double)
+
+    return doubleLocal(new ReaderTaskEither(taskEither.of))
+      .run(1)
+      .run()
+      .then(e => assert.deepEqual(e, eitherRight(2)))
+  })
+
+  it('left', () => {
+    return left(task.of(1))
+      .run({})
+      .run()
+      .then(e => {
+        assert.deepEqual(e, eitherLeft(1))
+      })
+  })
+
+  it('right', () => {
+    return right(task.of(1))
+      .run({})
+      .run()
+      .then(e => {
+        assert.deepEqual(e, eitherRight(1))
+      })
+  })
+
+  it('fromEither', () => {
+    const fa = fromEither(either.of(1))
+    return fa
+      .run({})
+      .run()
+      .then(e => {
+        assert.deepEqual(e, eitherRight(1))
+      })
+  })
+
+  it('fromReader', () => {
+    const fa = fromReader(reader.of(1))
+    return fa
+      .run({})
+      .run()
+      .then(e => {
+        assert.deepEqual(e, eitherRight(1))
+      })
+  })
+
+  it('fromTask', () => {
+    const fa = fromTask(task.of(1))
+    return fa
+      .run({})
+      .run()
+      .then(e => {
+        assert.deepEqual(e, eitherRight(1))
+      })
+  })
+
+  it('fromTaskEither', () => {
+    const fa = fromTaskEither(taskEither.of(1))
+    return fa
+      .run({})
+      .run()
+      .then(e => {
+        assert.deepEqual(e, eitherRight(1))
+      })
+  })
+
+  it('tryCatch', () => {
+    const ok = tryCatch(() => Promise.resolve(1), () => 'error')
+    const ko = tryCatch(() => Promise.reject(undefined), () => 'error')
+    return Promise.all([ok.run({}).run(), ko.run({}).run()]).then(([eok, eko]) => {
+      assert.deepEqual(eok, eitherRight(1))
+      assert.deepEqual(eko, eitherLeft('error'))
+    })
+  })
+})