-
-
Notifications
You must be signed in to change notification settings - Fork 503
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add readerTask & getReaderTaskValidation
- Loading branch information
Showing
5 changed files
with
403 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
import { IO } from './IO' | ||
import { Monad2 } from './Monad' | ||
import { MonadTask2 } from './MonadTask' | ||
import { Monoid } from './Monoid' | ||
import { pipeable } from './pipeable' | ||
import { getSemigroup as getReaderSemigroup, Reader } from './Reader' | ||
import { getReaderM } from './ReaderT' | ||
import { Semigroup } from './Semigroup' | ||
import * as TA from './Task' | ||
|
||
import Task = TA.Task | ||
|
||
const T = getReaderM(TA.task) | ||
|
||
declare module './HKT' { | ||
interface URItoKind2<E, A> { | ||
ReaderTask: ReaderTask<E, A> | ||
} | ||
} | ||
|
||
/** | ||
* @since 2.3.0 | ||
*/ | ||
export const URI = 'ReaderTask' | ||
|
||
/** | ||
* @since 2.3.0 | ||
*/ | ||
export type URI = typeof URI | ||
|
||
/** | ||
* @since 2.3.0 | ||
*/ | ||
export interface ReaderTask<R, A> { | ||
(r: R): Task<A> | ||
} | ||
|
||
/** | ||
* @since 2.3.0 | ||
*/ | ||
export function run<R, A>(ma: ReaderTask<R, A>, r: R): Promise<A> { | ||
return ma(r)() | ||
} | ||
|
||
/** | ||
* @since 2.3.0 | ||
*/ | ||
export const fromTask: <R, A>(ma: Task<A>) => ReaderTask<R, A> = T.fromM | ||
|
||
/** | ||
* @since 2.3.0 | ||
*/ | ||
export const reader: <R, A = never>(ma: Reader<R, A>) => ReaderTask<R, A> = T.fromReader | ||
|
||
/** | ||
* @since 2.3.0 | ||
*/ | ||
export function fromIO<R, A>(ma: IO<A>): ReaderTask<R, A> { | ||
return fromTask(TA.fromIO(ma)) | ||
} | ||
|
||
/** | ||
* @since 2.3.0 | ||
*/ | ||
export function of<R, A>(a: A): ReaderTask<R, A> { | ||
return fromTask(TA.of(a)) | ||
} | ||
|
||
/** | ||
* @since 2.3.0 | ||
*/ | ||
export function fromReader<R, A>(ma: Reader<R, A>): ReaderTask<R, A> { | ||
return r => TA.of(ma(r)) | ||
} | ||
|
||
/** | ||
* @since 2.3.0 | ||
*/ | ||
export function getSemigroup<R, A>(S: Semigroup<A>): Semigroup<ReaderTask<R, A>> { | ||
return getReaderSemigroup(TA.getSemigroup<A>(S)) | ||
} | ||
|
||
/** | ||
* @since 2.3.0 | ||
*/ | ||
export function getMonoid<R, A>(M: Monoid<A>): Monoid<ReaderTask<R, A>> { | ||
return { | ||
concat: getSemigroup<R, A>(M).concat, | ||
empty: of(M.empty) | ||
} | ||
} | ||
|
||
/** | ||
* @since 2.3.0 | ||
*/ | ||
export const ask: <R>() => ReaderTask<R, R> = T.ask | ||
|
||
/** | ||
* @since 2.3.0 | ||
*/ | ||
export const asks: <R, A = never>(f: (r: R) => A) => ReaderTask<R, A> = T.asks | ||
|
||
/** | ||
* @since 2.3.0 | ||
*/ | ||
export function local<Q, R>(f: (f: Q) => R): <E, A>(ma: ReaderTask<R, A>) => ReaderTask<Q, A> { | ||
return ma => T.local(ma, f) | ||
} | ||
|
||
/** | ||
* @since 2.3.0 | ||
*/ | ||
|
||
export const readerTask: Monad2<URI> & MonadTask2<URI> = { | ||
URI, | ||
map: T.map, | ||
of, | ||
ap: T.ap, | ||
chain: T.chain, | ||
fromIO, | ||
fromTask | ||
} | ||
|
||
/** | ||
* Like `readerTask` but `ap` is sequential | ||
* @since 2.3.0 | ||
*/ | ||
export const readerTaskSeq: typeof readerTask = { | ||
...readerTask, | ||
ap: (mab, ma) => T.chain(mab, f => T.map(ma, f)) | ||
} | ||
|
||
const { ap, apFirst, apSecond, chain, chainFirst, flatten, map } = pipeable(readerTask) | ||
|
||
export { | ||
/** | ||
* @since 2.3.0 | ||
*/ | ||
ap, | ||
/** | ||
* @since 2.3.0 | ||
*/ | ||
apFirst, | ||
/** | ||
* @since 2.3.0 | ||
*/ | ||
apSecond, | ||
/** | ||
* @since 2.3.0 | ||
*/ | ||
chain, | ||
/** | ||
* @since 2.3.0 | ||
*/ | ||
chainFirst, | ||
/** | ||
* @since 2.3.0 | ||
*/ | ||
flatten, | ||
/** | ||
* @since 2.3.0 | ||
*/ | ||
map | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
import * as assert from 'assert' | ||
import { array } from '../src/Array' | ||
import { pipe } from '../src/pipeable' | ||
import { reader } from '../src/Reader' | ||
import * as _ from '../src/ReaderTask' | ||
import { task } from '../src/Task' | ||
import { monoidString } from '../src/Monoid' | ||
import { semigroupString } from '../src/Semigroup' | ||
|
||
describe('ReaderTask', () => { | ||
describe('Monad', () => { | ||
it('map', async () => { | ||
const double = (n: number): number => n * 2 | ||
const x = await _.run(_.readerTask.map(_.of(1), double), {}) | ||
assert.deepStrictEqual(x, 2) | ||
}) | ||
|
||
it('ap', async () => { | ||
const double = (n: number): number => n * 2 | ||
const mab = _.of(double) | ||
const ma = _.of(1) | ||
const x = await _.run(_.readerTask.ap(mab, ma), {}) | ||
assert.deepStrictEqual(x, 2) | ||
}) | ||
|
||
it('chain', async () => { | ||
const f = (a: string) => _.of(a.length) | ||
const e1 = await _.run(_.readerTask.chain(_.of('foo'), f), {}) | ||
assert.deepStrictEqual(e1, 3) | ||
}) | ||
|
||
describe('readerTaskSeq', () => { | ||
it('chain ', async () => { | ||
const f = (a: string) => _.of(a.length) | ||
const e1 = await _.run(_.readerTaskSeq.chain(_.of('foo'), f), {}) | ||
assert.deepStrictEqual(e1, 3) | ||
}) | ||
}) | ||
}) | ||
|
||
it('ask', async () => { | ||
const e = await _.run(_.ask<number>(), 1) | ||
return assert.deepStrictEqual(e, 1) | ||
}) | ||
|
||
it('asks', async () => { | ||
const e = await _.run( | ||
_.asks((s: string) => s.length), | ||
'foo' | ||
) | ||
return assert.deepStrictEqual(e, 3) | ||
}) | ||
|
||
it('local', async () => { | ||
const len = (s: string): number => s.length | ||
const e = await _.run( | ||
pipe( | ||
_.asks((n: number) => n + 1), | ||
_.local(len) | ||
), | ||
'aaa' | ||
) | ||
assert.deepStrictEqual(e, 4) | ||
}) | ||
|
||
it('fromTask', async () => { | ||
const e = await _.run(_.fromTask(task.of(1)), {}) | ||
assert.deepStrictEqual(e, 1) | ||
}) | ||
|
||
it('fromReader', async () => { | ||
const e = await _.fromReader(reader.of(1))({})() | ||
assert.deepStrictEqual(e, 1) | ||
}) | ||
|
||
it('getSemigroup', async () => { | ||
const M = _.getSemigroup(semigroupString) | ||
const e = await M.concat(_.of('a'), _.of('b'))({})() | ||
assert.strictEqual(e, 'ab') | ||
}) | ||
|
||
it('getMonoid', async () => { | ||
const M = _.getMonoid(monoidString) | ||
const e = await M.concat(_.of('a'), M.empty)({})() | ||
assert.strictEqual(e, 'a') | ||
const e2 = await M.concat(M.empty, _.of('b'))({})() | ||
assert.strictEqual(e2, 'b') | ||
const e3 = await M.concat(_.of('a'), _.of('b'))({})() | ||
assert.strictEqual(e3, 'ab') | ||
}) | ||
|
||
it('reader', async () => { | ||
const e = await _.run(_.reader(reader.of(1)), {}) | ||
assert.deepStrictEqual(e, 1) | ||
}) | ||
|
||
it('sequence parallel', async () => { | ||
const log: Array<string> = [] | ||
const append = (message: string): _.ReaderTask<{}, number> => _.fromTask(() => Promise.resolve(log.push(message))) | ||
const t1 = _.readerTask.chain(append('start 1'), () => append('end 1')) | ||
const t2 = _.readerTask.chain(append('start 2'), () => append('end 2')) | ||
const sequenceParallel = array.sequence(_.readerTask) | ||
const ns = await _.run(sequenceParallel([t1, t2]), {}) | ||
assert.deepStrictEqual(ns, [3, 4]) | ||
assert.deepStrictEqual(log, ['start 1', 'start 2', 'end 1', 'end 2']) | ||
}) | ||
|
||
it('sequence series', async () => { | ||
const log: Array<string> = [] | ||
const append = (message: string): _.ReaderTask<{}, number> => _.fromTask(() => Promise.resolve(log.push(message))) | ||
const t1 = _.readerTask.chain(append('start 1'), () => append('end 1')) | ||
const t2 = _.readerTask.chain(append('start 2'), () => append('end 2')) | ||
const sequenceSeries = array.sequence(_.readerTaskSeq) | ||
const ns = await _.run(sequenceSeries([t1, t2]), {}) | ||
assert.deepStrictEqual(ns, [2, 4]) | ||
assert.deepStrictEqual(log, ['start 1', 'end 1', 'start 2', 'end 2']) | ||
}) | ||
|
||
describe('MonadIO', () => { | ||
it('fromIO', async () => { | ||
const e = await _.run( | ||
_.readerTask.fromIO(() => 1), | ||
{} | ||
) | ||
assert.deepStrictEqual(e, 1) | ||
}) | ||
}) | ||
}) |
Oops, something went wrong.