Repository: gcanti/fp-ts
Pull request #1325 (2020-10-07 17:31:13)

IOEither: add ApplicativePar, ApplicativeSeq


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2ddc5b5a..1daa710b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,16 @@
 **Note**: A feature tagged as Experimental is in a
 high state of flux, you're at risk of it changing without notice.
 
+# 2.8.4
+
+- **Polish**
+  - `IOEither`
+    - add `ApplicativePar` instance (@gcanti)
+    - add `ApplicativeSeq` instance (@gcanti)
+- **Deprecation**
+  - `IOEither`
+    - deprecate `Applicative` in favour of `ApplicativePar` (@gcanti)
+
 # 2.8.3
 
 - **Polish**
diff --git a/package.json b/package.json
index cffd9824..518b68ff 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "fp-ts",
-  "version": "2.8.3",
+  "version": "2.8.4",
   "description": "Functional programming in TypeScript",
   "main": "lib/index.js",
   "module": "es6/index.js",
diff --git a/src/IOEither.ts b/src/IOEither.ts
index 066e660a..b085db42 100644
--- a/src/IOEither.ts
+++ b/src/IOEither.ts
@@ -194,6 +194,11 @@ export const chainEitherK: <E, A, B>(
 const map_: Monad2<URI>['map'] = (fa, f) => pipe(fa, map(f))
 /* istanbul ignore next */
 const ap_: Monad2<URI>['ap'] = (fab, fa) => pipe(fab, ap(fa))
+const apSeq_: Applicative2<URI>['ap'] = (fab, fa) =>
+  pipe(
+    fab,
+    chain((f) => pipe(fa, map(f)))
+  )
 const of = right
 /* istanbul ignore next */
 const chain_: Monad2<URI>['chain'] = (ma, f) => pipe(ma, chain(f))
@@ -508,15 +513,34 @@ export const Bifunctor: Bifunctor2<URI> = {
 
 /**
  * @category instances
- * @since 2.7.0
+ * @since 2.8.4
  */
-export const Applicative: Applicative2<URI> = {
+export const ApplicativePar: Applicative2<URI> = {
   URI,
   map: map_,
   ap: ap_,
   of
 }
 
+/**
+ * @category instances
+ * @since 2.8.4
+ */
+export const ApplicativeSeq: Applicative2<URI> = {
+  URI,
+  map: map_,
+  ap: apSeq_,
+  of
+}
+
+/**
+ * Use `ApplicativePar` instead
+ *
+ * @since 2.7.0
+ * @deprecated
+ */
+export const Applicative: Applicative2<URI> = ApplicativePar
+
 /**
  * @category instances
  * @since 2.7.0


Test patch:
diff --git a/test/IOEither.ts b/test/IOEither.ts
index 0fb6ffa2..2aa304aa 100644
--- a/test/IOEither.ts
+++ b/test/IOEither.ts
@@ -58,6 +58,36 @@ describe('IOEither', () => {
       assert.deepStrictEqual(pipe(_.right(double), _.ap(_.right(1)))(), E.right(2))
     })
 
+    it('ApplicativePar', () => {
+      // tslint:disable-next-line: readonly-array
+      const log: Array<string> = []
+      const x = sequenceT(_.ApplicativePar)(
+        _.rightIO<string, number>(() => log.push('a')),
+        _.leftIO(() => {
+          log.push('b')
+          return 'error'
+        }),
+        _.rightIO(() => log.push('c'))
+      )()
+      assert.deepStrictEqual(x, E.left('error'))
+      assert.deepStrictEqual(log, ['a', 'b', 'c'])
+    })
+
+    it('ApplicativeSeq', () => {
+      // tslint:disable-next-line: readonly-array
+      const log: Array<string> = []
+      const x = sequenceT(_.ApplicativeSeq)(
+        _.rightIO<string, number>(() => log.push('a')),
+        _.leftIO(() => {
+          log.push('b')
+          return 'error'
+        }),
+        _.rightIO(() => log.push('c'))
+      )()
+      assert.deepStrictEqual(x, E.left('error'))
+      assert.deepStrictEqual(log, ['a', 'b'])
+    })
+
     it('apFirst', () => {
       assert.deepStrictEqual(pipe(_.right('a'), _.apFirst(_.right('b')))(), E.right('a'))
     })