diff --git a/CHANGELOG.md b/CHANGELOG.md index aff141a3c..377b75a04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ high state of flux, you're at risk of it changing without notice. - `Option` - `ReadonlyArray` - `State` + - `Task` # 2.13.2 diff --git a/src/Task.ts b/src/Task.ts index fd2d51523..0c548a7c5 100644 --- a/src/Task.ts +++ b/src/Task.ts @@ -21,7 +21,7 @@ import { import { bind as bind_, Chain1, chainFirst as chainFirst_ } from './Chain' import { chainFirstIOK as chainFirstIOK_, chainIOK as chainIOK_, FromIO1, fromIOK as fromIOK_ } from './FromIO' import { FromTask1 } from './FromTask' -import { identity, pipe } from './function' +import { dual, identity, pipe } from './function' import { bindTo as bindTo_, flap as flap_, Functor1, let as let__ } from './Functor' import * as _ from './internal' import { IO } from './IO' @@ -102,7 +102,6 @@ const _apSeq: Apply1['ap'] = (fab, fa) => fab, chain((f) => pipe(fa, map(f))) ) -const _chain: Chain1['chain'] = (ma, f) => pipe(ma, chain(f)) /** * `map` can be used to turn functions `(a: A) => B` into functions `(fa: F) => F` whose argument and return types @@ -127,15 +126,28 @@ export const ap: (fa: Task) => (fab: Task<(a: A) => B>) => Task = (f export const of: (a: A) => Task = (a) => () => Promise.resolve(a) /** - * Composes computations in sequence, using the return value of one computation to determine the next computation. + * @category sequencing + * @since 2.14.0 + */ +export const flatMap: { + (f: (a: A) => Task): (ma: Task) => Task + (ma: Task, f: (a: A) => Task): Task +} = dual( + 2, + (ma: Task, f: (a: A) => Task): Task => + () => + Promise.resolve() + .then(ma) + .then((a) => f(a)()) +) + +/** + * Alias of `flatMap`. * * @category sequencing * @since 2.0.0 */ -export const chain: (f: (a: A) => Task) => (ma: Task) => Task = (f) => (ma) => () => - Promise.resolve() - .then(ma) - .then((a) => f(a)()) +export const chain: (f: (a: A) => Task) => (ma: Task) => Task = flatMap /** * @category sequencing @@ -284,7 +296,7 @@ export const Chain: Chain1 = { URI, map: _map, ap: _apPar, - chain: _chain + chain: flatMap } /** @@ -296,7 +308,7 @@ export const Monad: Monad1 = { map: _map, of, ap: _apPar, - chain: _chain + chain: flatMap } /** @@ -308,7 +320,7 @@ export const MonadIO: MonadIO1 = { map: _map, of, ap: _apPar, - chain: _chain, + chain: flatMap, fromIO } @@ -328,7 +340,7 @@ export const MonadTask: MonadTask1 = { map: _map, of, ap: _apPar, - chain: _chain, + chain: flatMap, fromIO, fromTask } @@ -581,7 +593,7 @@ export const task: Monad1 & MonadTask1 = { map: _map, of, ap: _apPar, - chain: _chain, + chain: flatMap, fromIO, fromTask } @@ -600,7 +612,7 @@ export const taskSeq: Monad1 & MonadTask1 = { map: _map, of, ap: _apSeq, - chain: _chain, + chain: flatMap, fromIO, fromTask } diff --git a/test/Task.ts b/test/Task.ts index 7fb7a3423..bb73623f6 100644 --- a/test/Task.ts +++ b/test/Task.ts @@ -79,6 +79,15 @@ describe('Task', () => { await deepStrictEqual(a, b, 'b', ['b', 'a']) }) + it('flatMap', async () => { + const f = + (n: number): _.Task => + () => + Promise.resolve(n * 2) + U.deepStrictEqual(await pipe(delay(1, 2), _.flatMap(f))(), 4) + U.deepStrictEqual(await _.flatMap(delay(1, 2), f)(), 4) + }) + it('chain', async () => { const f = (n: number): _.Task =>