Skip to content

Commit 7f20d60

Browse files
committed
deprecate foldM in favour of reduceM
1 parent b87295d commit 7f20d60

File tree

4 files changed

+186
-73
lines changed

4 files changed

+186
-73
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ high state of flux, you're at risk of it changing without notice.
3434
- add `getFilterable` (@gcanti)
3535
- `Foldable`
3636
- add `toArray`, #1272 (@newswim)
37+
- add `reduceM` (@gcanti)
3738
- `Identity`
3839
- add `apS` (@gcanti)
3940
- add `bind` (@gcanti)
@@ -134,6 +135,8 @@ high state of flux, you're at risk of it changing without notice.
134135
- add `evaluate` (@gcanti)
135136
- add `execute` (@gcanti)
136137
- **Deprecation**
138+
- `Foldable`
139+
- deprecate `foldM` in favour of `reduceM` (@gcanti)
137140
- `State`
138141
- deprecate `evalState` in favour of `evaluate` (@gcanti)
139142
- deprecate `execState` in favour of `execute` (@gcanti)

docs/modules/Foldable.ts.md

+92-52
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,12 @@ Added in v2.0.0
2929
- [FoldableComposition22 (interface)](#foldablecomposition22-interface)
3030
- [FoldableComposition22C (interface)](#foldablecomposition22c-interface)
3131
- [FoldableComposition2C1 (interface)](#foldablecomposition2c1-interface)
32-
- [foldM](#foldm)
3332
- [getFoldableComposition](#getfoldablecomposition)
3433
- [intercalate](#intercalate)
34+
- [reduceM](#reducem)
3535
- [toArray](#toarray)
3636
- [traverse\_](#traverse_)
37+
- [~~foldM~~](#foldm)
3738

3839
---
3940

@@ -260,57 +261,6 @@ export interface FoldableComposition2C1<F extends URIS2, G extends URIS, E> {
260261

261262
Added in v2.0.0
262263

263-
## foldM
264-
265-
Similar to 'reduce', but the result is encapsulated in a monad.
266-
267-
Note: this function is not generally stack-safe, e.g., for monads which build up thunks a la `IO`.
268-
269-
**Signature**
270-
271-
```ts
272-
export declare function foldM<M extends URIS3, F extends URIS>(
273-
M: Monad3<M>,
274-
F: Foldable1<F>
275-
): <R, E, A, B>(fa: Kind<F, A>, b: B, f: (b: B, a: A) => Kind3<M, R, E, B>) => Kind3<M, R, E, B>
276-
export declare function foldM<M extends URIS3, F extends URIS, E>(
277-
M: Monad3C<M, E>,
278-
F: Foldable1<F>
279-
): <R, A, B>(fa: Kind<F, A>, b: B, f: (b: B, a: A) => Kind3<M, R, E, B>) => Kind3<M, R, E, B>
280-
export declare function foldM<M extends URIS2, F extends URIS>(
281-
M: Monad2<M>,
282-
F: Foldable1<F>
283-
): <E, A, B>(fa: Kind<F, A>, b: B, f: (b: B, a: A) => Kind2<M, E, B>) => Kind2<M, E, B>
284-
export declare function foldM<M extends URIS2, F extends URIS, E>(
285-
M: Monad2C<M, E>,
286-
F: Foldable1<F>
287-
): <A, B>(fa: Kind<F, A>, b: B, f: (b: B, a: A) => Kind2<M, E, B>) => Kind2<M, E, B>
288-
export declare function foldM<M extends URIS, F extends URIS>(
289-
M: Monad1<M>,
290-
F: Foldable1<F>
291-
): <A, B>(fa: Kind<F, A>, b: B, f: (b: B, a: A) => Kind<M, B>) => Kind<M, B>
292-
export declare function foldM<M, F>(
293-
M: Monad<M>,
294-
F: Foldable<F>
295-
): <A, B>(fa: HKT<F, A>, b: B, f: (b: B, a: A) => HKT<M, B>) => HKT<M, B>
296-
```
297-
298-
**Example**
299-
300-
```ts
301-
import { foldM } from 'fp-ts/Foldable'
302-
import { option, some } from 'fp-ts/Option'
303-
import { make, tree } from 'fp-ts/Tree'
304-
305-
const t = make(1, [make(2, []), make(3, []), make(4, [])])
306-
assert.deepStrictEqual(
307-
foldM(option, tree)(t, 0, (b, a) => (a > 2 ? some(b + a) : some(b))),
308-
some(7)
309-
)
310-
```
311-
312-
Added in v2.0.0
313-
314264
## getFoldableComposition
315265

316266
Returns the composition of two foldables
@@ -400,6 +350,61 @@ assert.strictEqual(intercalate(monoidString, tree)('|', t), 'a|b|c|d')
400350

401351
Added in v2.0.0
402352

353+
## reduceM
354+
355+
Similar to 'reduce', but the result is encapsulated in a monad.
356+
357+
Note: this function is not generally stack-safe, e.g., for monads which build up thunks a la `IO`.
358+
359+
**Signature**
360+
361+
```ts
362+
export declare function reduceM<M extends URIS3, F extends URIS>(
363+
M: Monad3<M>,
364+
F: Foldable1<F>
365+
): <B, A, R, E>(b: B, f: (b: B, a: A) => Kind3<M, R, E, B>) => (fa: Kind<F, A>) => Kind3<M, R, E, B>
366+
export declare function reduceM<M extends URIS3, F extends URIS, E>(
367+
M: Monad3C<M, E>,
368+
F: Foldable1<F>
369+
): <B, A, R>(b: B, f: (b: B, a: A) => Kind3<M, R, E, B>) => (fa: Kind<F, A>) => Kind3<M, R, E, B>
370+
export declare function reduceM<M extends URIS2, F extends URIS>(
371+
M: Monad2<M>,
372+
F: Foldable1<F>
373+
): <B, A, E>(b: B, f: (b: B, a: A) => Kind2<M, E, B>) => (fa: Kind<F, A>) => Kind2<M, E, B>
374+
export declare function reduceM<M extends URIS2, F extends URIS, E>(
375+
M: Monad2C<M, E>,
376+
F: Foldable1<F>
377+
): <B, A>(b: B, f: (b: B, a: A) => Kind2<M, E, B>) => (fa: Kind<F, A>) => Kind2<M, E, B>
378+
export declare function reduceM<M extends URIS, F extends URIS>(
379+
M: Monad1<M>,
380+
F: Foldable1<F>
381+
): <B, A>(b: B, f: (b: B, a: A) => Kind<M, B>) => (fa: Kind<F, A>) => Kind<M, B>
382+
export declare function reduceM<M, F>(
383+
M: Monad<M>,
384+
F: Foldable<F>
385+
): <B, A>(b: B, f: (b: B, a: A) => HKT<M, B>) => (fa: HKT<F, A>) => HKT<M, B>
386+
```
387+
388+
**Example**
389+
390+
```ts
391+
import { reduceM } from 'fp-ts/Foldable'
392+
import { Monad, some } from 'fp-ts/Option'
393+
import { make, Foldable } from 'fp-ts/Tree'
394+
import { pipe } from 'fp-ts/function'
395+
396+
const t = make(1, [make(2, []), make(3, []), make(4, [])])
397+
assert.deepStrictEqual(
398+
pipe(
399+
t,
400+
reduceM(Monad, Foldable)(0, (b, a) => (a > 2 ? some(b + a) : some(b)))
401+
),
402+
some(7)
403+
)
404+
```
405+
406+
Added in v2.8.0
407+
403408
## toArray
404409

405410
Transforms a `Foldable` into a read-only array.
@@ -476,3 +481,38 @@ assert.strictEqual(log, 'abc')
476481
```
477482

478483
Added in v2.0.0
484+
485+
## ~~foldM~~
486+
487+
Use `reduceM` instead
488+
489+
**Signature**
490+
491+
```ts
492+
export declare function foldM<M extends URIS3, F extends URIS>(
493+
M: Monad3<M>,
494+
F: Foldable1<F>
495+
): <R, E, A, B>(fa: Kind<F, A>, b: B, f: (b: B, a: A) => Kind3<M, R, E, B>) => Kind3<M, R, E, B>
496+
export declare function foldM<M extends URIS3, F extends URIS, E>(
497+
M: Monad3C<M, E>,
498+
F: Foldable1<F>
499+
): <R, A, B>(fa: Kind<F, A>, b: B, f: (b: B, a: A) => Kind3<M, R, E, B>) => Kind3<M, R, E, B>
500+
export declare function foldM<M extends URIS2, F extends URIS>(
501+
M: Monad2<M>,
502+
F: Foldable1<F>
503+
): <E, A, B>(fa: Kind<F, A>, b: B, f: (b: B, a: A) => Kind2<M, E, B>) => Kind2<M, E, B>
504+
export declare function foldM<M extends URIS2, F extends URIS, E>(
505+
M: Monad2C<M, E>,
506+
F: Foldable1<F>
507+
): <A, B>(fa: Kind<F, A>, b: B, f: (b: B, a: A) => Kind2<M, E, B>) => Kind2<M, E, B>
508+
export declare function foldM<M extends URIS, F extends URIS>(
509+
M: Monad1<M>,
510+
F: Foldable1<F>
511+
): <A, B>(fa: Kind<F, A>, b: B, f: (b: B, a: A) => Kind<M, B>) => Kind<M, B>
512+
export declare function foldM<M, F>(
513+
M: Monad<M>,
514+
F: Foldable<F>
515+
): <A, B>(fa: HKT<F, A>, b: B, f: (b: B, a: A) => HKT<M, B>) => HKT<M, B>
516+
```
517+
518+
Added in v2.0.0

src/Foldable.ts

+54-12
Original file line numberDiff line numberDiff line change
@@ -214,42 +214,37 @@ export function getFoldableComposition<F, G>(F: Foldable<F>, G: Foldable<G>): Fo
214214
}
215215
}
216216

217-
// TODO: rename to `reduceM` in v3
218217
/**
219-
* Similar to 'reduce', but the result is encapsulated in a monad.
220-
*
221-
* Note: this function is not generally stack-safe, e.g., for monads which build up thunks a la `IO`.
222-
*
223-
* @example
224-
* import { foldM } from 'fp-ts/Foldable'
225-
* import { option, some } from 'fp-ts/Option'
226-
* import { make, tree } from 'fp-ts/Tree'
227-
*
228-
* const t = make(1, [make(2, []), make(3, []), make(4, [])])
229-
* assert.deepStrictEqual(foldM(option, tree)(t, 0, (b, a) => (a > 2 ? some(b + a) : some(b))), some(7))
218+
* Use `reduceM` instead
230219
*
231220
* @since 2.0.0
221+
* @deprecated
232222
*/
233223
export function foldM<M extends URIS3, F extends URIS>(
234224
M: Monad3<M>,
235225
F: Foldable1<F>
236226
): <R, E, A, B>(fa: Kind<F, A>, b: B, f: (b: B, a: A) => Kind3<M, R, E, B>) => Kind3<M, R, E, B>
227+
/** @deprecated */
237228
export function foldM<M extends URIS3, F extends URIS, E>(
238229
M: Monad3C<M, E>,
239230
F: Foldable1<F>
240231
): <R, A, B>(fa: Kind<F, A>, b: B, f: (b: B, a: A) => Kind3<M, R, E, B>) => Kind3<M, R, E, B>
232+
/** @deprecated */
241233
export function foldM<M extends URIS2, F extends URIS>(
242234
M: Monad2<M>,
243235
F: Foldable1<F>
244236
): <E, A, B>(fa: Kind<F, A>, b: B, f: (b: B, a: A) => Kind2<M, E, B>) => Kind2<M, E, B>
237+
/** @deprecated */
245238
export function foldM<M extends URIS2, F extends URIS, E>(
246239
M: Monad2C<M, E>,
247240
F: Foldable1<F>
248241
): <A, B>(fa: Kind<F, A>, b: B, f: (b: B, a: A) => Kind2<M, E, B>) => Kind2<M, E, B>
242+
/** @deprecated */
249243
export function foldM<M extends URIS, F extends URIS>(
250244
M: Monad1<M>,
251245
F: Foldable1<F>
252246
): <A, B>(fa: Kind<F, A>, b: B, f: (b: B, a: A) => Kind<M, B>) => Kind<M, B>
247+
/** @deprecated */
253248
export function foldM<M, F>(
254249
M: Monad<M>,
255250
F: Foldable<F>
@@ -261,6 +256,53 @@ export function foldM<M, F>(
261256
return (fa, b, f) => F.reduce(fa, M.of(b), (mb, a) => M.chain(mb, (b) => f(b, a)))
262257
}
263258

259+
/**
260+
* Similar to 'reduce', but the result is encapsulated in a monad.
261+
*
262+
* Note: this function is not generally stack-safe, e.g., for monads which build up thunks a la `IO`.
263+
*
264+
* @example
265+
* import { reduceM } from 'fp-ts/Foldable'
266+
* import { Monad, some } from 'fp-ts/Option'
267+
* import { make, Foldable } from 'fp-ts/Tree'
268+
* import { pipe } from 'fp-ts/function'
269+
*
270+
* const t = make(1, [make(2, []), make(3, []), make(4, [])])
271+
* assert.deepStrictEqual(pipe(t, reduceM(Monad, Foldable)(0, (b, a) => (a > 2 ? some(b + a) : some(b)))), some(7))
272+
*
273+
* @since 2.8.0
274+
*/
275+
export function reduceM<M extends URIS3, F extends URIS>(
276+
M: Monad3<M>,
277+
F: Foldable1<F>
278+
): <B, A, R, E>(b: B, f: (b: B, a: A) => Kind3<M, R, E, B>) => (fa: Kind<F, A>) => Kind3<M, R, E, B>
279+
export function reduceM<M extends URIS3, F extends URIS, E>(
280+
M: Monad3C<M, E>,
281+
F: Foldable1<F>
282+
): <B, A, R>(b: B, f: (b: B, a: A) => Kind3<M, R, E, B>) => (fa: Kind<F, A>) => Kind3<M, R, E, B>
283+
export function reduceM<M extends URIS2, F extends URIS>(
284+
M: Monad2<M>,
285+
F: Foldable1<F>
286+
): <B, A, E>(b: B, f: (b: B, a: A) => Kind2<M, E, B>) => (fa: Kind<F, A>) => Kind2<M, E, B>
287+
export function reduceM<M extends URIS2, F extends URIS, E>(
288+
M: Monad2C<M, E>,
289+
F: Foldable1<F>
290+
): <B, A>(b: B, f: (b: B, a: A) => Kind2<M, E, B>) => (fa: Kind<F, A>) => Kind2<M, E, B>
291+
export function reduceM<M extends URIS, F extends URIS>(
292+
M: Monad1<M>,
293+
F: Foldable1<F>
294+
): <B, A>(b: B, f: (b: B, a: A) => Kind<M, B>) => (fa: Kind<F, A>) => Kind<M, B>
295+
export function reduceM<M, F>(
296+
M: Monad<M>,
297+
F: Foldable<F>
298+
): <B, A>(b: B, f: (b: B, a: A) => HKT<M, B>) => (fa: HKT<F, A>) => HKT<M, B>
299+
export function reduceM<M, F>(
300+
M: Monad<M>,
301+
F: Foldable<F>
302+
): <B, A>(b: B, f: (b: B, a: A) => HKT<M, B>) => (fa: HKT<F, A>) => HKT<M, B> {
303+
return (b, f) => (fa) => F.reduce(fa, M.of(b), (mb, a) => M.chain(mb, (b) => f(b, a)))
304+
}
305+
264306
// TODO: curry in v3
265307
/**
266308
* Fold a data structure, accumulating values in some `Monoid`, combining adjacent elements using the specified separator

test/Foldable.ts

+37-9
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,16 @@ import * as I from '../src/IO'
44
import * as O from '../src/Option'
55
import * as T from '../src/Tree'
66
import { monoidString } from '../src/Monoid'
7-
import { foldM, getFoldableComposition, intercalate, traverse_, toArray } from '../src/Foldable'
7+
import * as _ from '../src/Foldable'
8+
import { pipe } from '../src/function'
89

910
export const ArrayOptionURI = 'ArrayOption'
1011

1112
export type ArrayOptionURI = typeof ArrayOptionURI
1213

1314
describe('Foldable', () => {
1415
it('getFoldableComposition', () => {
15-
const F = getFoldableComposition(A.Foldable, O.Foldable)
16+
const F = _.getFoldableComposition(A.Foldable, O.Foldable)
1617
// reduce
1718
assert.deepStrictEqual(F.reduce([O.some('a'), O.some('b'), O.some('c')], '', monoidString.concat), 'abc')
1819
assert.deepStrictEqual(F.reduce([O.none, O.some('b'), O.none], '', monoidString.concat), 'b')
@@ -43,38 +44,65 @@ describe('Foldable', () => {
4344
})
4445

4546
it('intercalate', () => {
46-
assert.deepStrictEqual(intercalate(monoidString, A.Foldable)(',', ['a', 'b', 'c']), 'a,b,c')
47+
assert.deepStrictEqual(_.intercalate(monoidString, A.Foldable)(',', ['a', 'b', 'c']), 'a,b,c')
4748
})
4849

4950
it('toArray', () => {
5051
// Option
51-
const optionToArray = toArray(O.option)
52+
const optionToArray = _.toArray(O.option)
5253
assert.deepStrictEqual(optionToArray(O.some(1)), [1])
5354
assert.deepStrictEqual(optionToArray(O.none), [])
5455

5556
// Tree
56-
const treeToArray = toArray(T.tree)
57+
const treeToArray = _.toArray(T.tree)
5758
assert.deepStrictEqual(treeToArray(T.make(1, [T.make(2, []), T.make(3, []), T.make(4, [])])), [1, 2, 3, 4])
5859
})
5960

6061
it('traverse_', () => {
6162
let log = ''
6263
const append = (s: String) => () => (log += s)
63-
traverse_(I.Applicative, A.Foldable)(['a', 'b', 'c'], append)()
64+
_.traverse_(I.Applicative, A.Foldable)(['a', 'b', 'c'], append)()
6465
assert.deepStrictEqual(log, 'abc')
6566
})
6667

6768
it('foldM', () => {
6869
assert.deepStrictEqual(
69-
foldM(O.Monad, A.Foldable)([], 1, () => O.none),
70+
// tslint:disable-next-line: deprecation
71+
_.foldM(O.Monad, A.Foldable)([], 1, () => O.none),
7072
O.some(1)
7173
)
7274
assert.deepStrictEqual(
73-
foldM(O.Monad, A.Foldable)([2], 1, () => O.none),
75+
// tslint:disable-next-line: deprecation
76+
_.foldM(O.Monad, A.Foldable)([2], 1, () => O.none),
7477
O.none
7578
)
7679
assert.deepStrictEqual(
77-
foldM(O.Monad, A.Foldable)([2], 1, (b, a) => O.some(b + a)),
80+
// tslint:disable-next-line: deprecation
81+
_.foldM(O.Monad, A.Foldable)([2], 1, (b, a) => O.some(b + a)),
82+
O.some(3)
83+
)
84+
})
85+
86+
it('reduceM', () => {
87+
assert.deepStrictEqual(
88+
pipe(
89+
[],
90+
_.reduceM(O.Monad, A.Foldable)(1, () => O.none)
91+
),
92+
O.some(1)
93+
)
94+
assert.deepStrictEqual(
95+
pipe(
96+
[2],
97+
_.reduceM(O.Monad, A.Foldable)(1, () => O.none)
98+
),
99+
O.none
100+
)
101+
assert.deepStrictEqual(
102+
pipe(
103+
[2],
104+
_.reduceM(O.Monad, A.Foldable)(1, (b, a) => O.some(b + a))
105+
),
78106
O.some(3)
79107
)
80108
})

0 commit comments

Comments
 (0)