Repository: gcanti/fp-ts
Pull request #1458 (2021-03-29 17:07:03)

Add filterE utils to Witherable
**Before submitting a pull request,** please make sure the following is done:

- Fork [the repository](https://github.com/gcanti/fp-ts) and create your branch from `master`.
- Run `npm install` in the repository root.
- If you've fixed a bug or added code that should be tested, add tests!
- Ensure the test suite passes (`npm test`).

**Note**. If you've fixed a bug please link the related issue or, if missing, open an issue before sending a PR.

**Note**. If you find a typo in the **documentation**, make sure to modify the corresponding source (docs are generated).

**Note**. If you want to send a PR related to `fp-ts@1.x` please create your branch from `1.x`



Patch:
diff --git a/docs/modules/Witherable.ts.md b/docs/modules/Witherable.ts.md
index f2934ae7..3e0c7e72 100644
--- a/docs/modules/Witherable.ts.md
+++ b/docs/modules/Witherable.ts.md
@@ -43,6 +43,7 @@ Added in v2.0.0
   - [Wither2 (interface)](#wither2-interface)
   - [Wither2C (interface)](#wither2c-interface)
   - [Wither3 (interface)](#wither3-interface)
+  - [filterE](#filtere)
 
 ---
 
@@ -691,3 +692,32 @@ export interface Wither3<W extends URIS3> {
 ```
 
 Added in v2.0.0
+
+## filterE
+
+**Signature**
+
+```ts
+export declare function filterE<G extends URIS>(
+  W: Witherable1<G>
+): {
+  <F extends URIS3>(F: Applicative3<F>): <A, E, R>(
+    predicate: (a: A) => Kind3<F, R, E, boolean>
+  ) => (as: Kind<G, A>) => Kind3<F, R, E, Kind<G, A>>
+  <F extends URIS3, E>(F: Applicative3C<F, E>): <A, R>(
+    predicate: (a: A) => Kind3<F, R, E, boolean>
+  ) => (as: Kind<G, A>) => Kind3<F, R, E, Kind<G, A>>
+  <F extends URIS2>(F: Applicative2<F>): <A, E>(
+    predicate: (a: A) => Kind2<F, E, boolean>
+  ) => (as: Kind<G, A>) => Kind2<F, E, Kind<G, A>>
+  <F extends URIS2, E>(F: Applicative2C<F, E>): <A>(
+    predicate: (a: A) => Kind2<F, E, boolean>
+  ) => (ga: Kind<G, A>) => Kind2<F, E, Kind<G, A>>
+  <F extends URIS>(F: Applicative1<F>): <A>(
+    predicate: (a: A) => Kind<F, boolean>
+  ) => (ga: Kind<G, A>) => Kind<F, Kind<G, A>>
+  <F>(F: Applicative<F>): <A>(predicate: (a: A) => HKT<F, boolean>) => (ga: Kind<G, A>) => HKT<F, Kind<G, A>>
+}
+```
+
+Added in v2.11.0
diff --git a/src/Witherable.ts b/src/Witherable.ts
index 602686c6..73da0bd4 100644
--- a/src/Witherable.ts
+++ b/src/Witherable.ts
@@ -6,7 +6,7 @@
  * @since 2.0.0
  */
 import { HKT, Kind, Kind2, Kind3, URIS, URIS2, URIS3 } from './HKT'
-import { Option } from './Option'
+import { none, some, Option } from './Option'
 import { Traversable, Traversable1, Traversable2, Traversable2C, Traversable3 } from './Traversable'
 import { Applicative, Applicative1, Applicative2, Applicative2C, Applicative3, Applicative3C } from './Applicative'
 import { Filterable, Filterable1, Filterable2, Filterable2C, Filterable3 } from './Filterable'
@@ -546,3 +546,34 @@ export interface PipeableWilt3<W extends URIS3> {
     f: (a: A) => HKT<F, Either<B, C>>
   ) => <WR, WE>(wa: Kind3<W, WR, WE, A>) => HKT<F, Separated<Kind3<W, WR, WE, B>, Kind3<W, WR, WE, C>>>
 }
+
+/**
+ * @since 2.11.0
+ */
+export function filterE<G extends URIS>(
+  W: Witherable1<G>
+): {
+  <F extends URIS3>(F: Applicative3<F>): <A, E, R>(
+    predicate: (a: A) => Kind3<F, R, E, boolean>
+  ) => (as: Kind<G, A>) => Kind3<F, R, E, Kind<G, A>>
+  <F extends URIS3, E>(F: Applicative3C<F, E>): <A, R>(
+    predicate: (a: A) => Kind3<F, R, E, boolean>
+  ) => (as: Kind<G, A>) => Kind3<F, R, E, Kind<G, A>>
+  <F extends URIS2>(F: Applicative2<F>): <A, E>(
+    predicate: (a: A) => Kind2<F, E, boolean>
+  ) => (as: Kind<G, A>) => Kind2<F, E, Kind<G, A>>
+  <F extends URIS2, E>(F: Applicative2C<F, E>): <A>(
+    predicate: (a: A) => Kind2<F, E, boolean>
+  ) => (ga: Kind<G, A>) => Kind2<F, E, Kind<G, A>>
+  <F extends URIS>(F: Applicative1<F>): <A>(
+    predicate: (a: A) => Kind<F, boolean>
+  ) => (ga: Kind<G, A>) => Kind<F, Kind<G, A>>
+  <F>(F: Applicative<F>): <A>(predicate: (a: A) => HKT<F, boolean>) => (ga: Kind<G, A>) => HKT<F, Kind<G, A>>
+} {
+  return <F>(
+    F: Applicative<F>
+  ): (<A>(predicate: (a: A) => HKT<F, boolean>) => (ga: Kind<G, A>) => HKT<F, Kind<G, A>>) => {
+    const witherF = W.wither(F)
+    return (predicate) => (ga) => witherF(ga, (a) => F.map(predicate(a), (b) => (b ? some(a) : none)))
+  }
+}


Test patch:
diff --git a/test/Witherable.ts b/test/Witherable.ts
new file mode 100644
index 00000000..28cf3177
--- /dev/null
+++ b/test/Witherable.ts
@@ -0,0 +1,25 @@
+import * as U from './util'
+import * as T from '../src/Task'
+import * as RT from '../src/ReaderTask'
+import * as _ from '../src/Witherable'
+import * as RA from '../src/ReadonlyArray'
+import * as RR from '../src/ReadonlyRecord'
+
+describe('Witherable', () => {
+  describe('filterE', () => {
+    it('Applicative1', async () => {
+      const filterEArray = _.filterE(RA.Witherable)(T.ApplicativePar)((n: number) => T.of(n % 2 === 0))
+      U.deepStrictEqual(await filterEArray([1, 2])(), [2])
+
+      const filterERecord = _.filterE(RR.Witherable)(T.ApplicativePar)((n: number) => T.of(n % 2 === 0))
+      U.deepStrictEqual(await filterERecord({ a: 1, b: 2 })(), { b: 2 })
+    })
+    it('Applicative2', async () => {
+      const filterEArray = _.filterE(RA.Witherable)(RT.ApplicativePar)((n: number) => RT.of(n % 2 === 0))
+      U.deepStrictEqual(await filterEArray([1, 2])({})(), [2])
+
+      const filterERecord = _.filterE(RR.Witherable)(RT.ApplicativePar)((n: number) => RT.of(n % 2 === 0))
+      U.deepStrictEqual(await filterERecord({ a: 1, b: 2 })({})(), { b: 2 })
+    })
+  })
+})