Skip to content

Commit

Permalink
Task: add flatMap
Browse files Browse the repository at this point in the history
  • Loading branch information
gcanti committed Apr 20, 2023
1 parent d070e3a commit ae33d60
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 13 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ high state of flux, you're at risk of it changing without notice.
- `Option`
- `ReadonlyArray`
- `State`
- `Task`

# 2.13.2

Expand Down
38 changes: 25 additions & 13 deletions src/Task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -102,7 +102,6 @@ const _apSeq: Apply1<URI>['ap'] = (fab, fa) =>
fab,
chain((f) => pipe(fa, map(f)))
)
const _chain: Chain1<URI>['chain'] = (ma, f) => pipe(ma, chain(f))

/**
* `map` can be used to turn functions `(a: A) => B` into functions `(fa: F<A>) => F<B>` whose argument and return types
Expand All @@ -127,15 +126,28 @@ export const ap: <A>(fa: Task<A>) => <B>(fab: Task<(a: A) => B>) => Task<B> = (f
export const of: <A>(a: A) => Task<A> = (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: {
<A, B>(f: (a: A) => Task<B>): (ma: Task<A>) => Task<B>
<A, B>(ma: Task<A>, f: (a: A) => Task<B>): Task<B>
} = dual(
2,
<A, B>(ma: Task<A>, f: (a: A) => Task<B>): Task<B> =>
() =>
Promise.resolve()
.then(ma)
.then((a) => f(a)())
)

/**
* Alias of `flatMap`.
*
* @category sequencing
* @since 2.0.0
*/
export const chain: <A, B>(f: (a: A) => Task<B>) => (ma: Task<A>) => Task<B> = (f) => (ma) => () =>
Promise.resolve()
.then(ma)
.then((a) => f(a)())
export const chain: <A, B>(f: (a: A) => Task<B>) => (ma: Task<A>) => Task<B> = flatMap

/**
* @category sequencing
Expand Down Expand Up @@ -284,7 +296,7 @@ export const Chain: Chain1<URI> = {
URI,
map: _map,
ap: _apPar,
chain: _chain
chain: flatMap
}

/**
Expand All @@ -296,7 +308,7 @@ export const Monad: Monad1<URI> = {
map: _map,
of,
ap: _apPar,
chain: _chain
chain: flatMap
}

/**
Expand All @@ -308,7 +320,7 @@ export const MonadIO: MonadIO1<URI> = {
map: _map,
of,
ap: _apPar,
chain: _chain,
chain: flatMap,
fromIO
}

Expand All @@ -328,7 +340,7 @@ export const MonadTask: MonadTask1<URI> = {
map: _map,
of,
ap: _apPar,
chain: _chain,
chain: flatMap,
fromIO,
fromTask
}
Expand Down Expand Up @@ -581,7 +593,7 @@ export const task: Monad1<URI> & MonadTask1<URI> = {
map: _map,
of,
ap: _apPar,
chain: _chain,
chain: flatMap,
fromIO,
fromTask
}
Expand All @@ -600,7 +612,7 @@ export const taskSeq: Monad1<URI> & MonadTask1<URI> = {
map: _map,
of,
ap: _apSeq,
chain: _chain,
chain: flatMap,
fromIO,
fromTask
}
Expand Down
9 changes: 9 additions & 0 deletions test/Task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,15 @@ describe('Task', () => {
await deepStrictEqual(a, b, 'b', ['b', 'a'])
})

it('flatMap', async () => {
const f =
(n: number): _.Task<number> =>
() =>
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<number> =>
Expand Down

0 comments on commit ae33d60

Please sign in to comment.