Repository: gcanti/fp-ts
Pull request #1442 (2021-03-25 09:03:12)

2.10.0 rc.6


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fcb204ef..5808f023 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,31 @@
 **Note**: A feature tagged as Experimental is in a
 high state of flux, you're at risk of it changing without notice.
 
+# 2.10.0-rc.6
+
+- **Bug Fix**
+  - `ReadonlyNonEmptyArray`
+    - remove circular dependency on `NonEmptyArray`, closes #1443
+- **Breaking Change** (with respect to `2.10.0-rc`)
+  - `EitherT`
+    - rename `match` to `matchE` and add `match`
+  - `IOEither`
+    - rename `match` / `matchW` to `matchE` / `matchWE` and add `match` / `matchW`
+  - `OptionT`
+    - rename `match` to `matchE` and add `match`
+  - `ReaderEither`
+    - rename `match` / `matchW` to `matchE` / `matchWE` and add `match` / `matchW`
+  - `ReaderTaskEither`
+    - rename `match` / `matchW` to `matchE` / `matchWE` and add `match` / `matchW`
+  - `TheseT`
+    - rename `match` to `matchE` and add `match`
+  - `TaskEither`
+    - rename `match` / `matchW` to `matchE` / `matchWE` and add `match` / `matchW`
+  - `TaskOption`
+    - rename `match` / `matchW` to `matchE` / `matchWE` and add `match` / `matchW`
+  - `TaskThese`
+    - rename `match` / `matchW` to `matchE` / `matchWE` and add `match` / `matchW`
+
 # 2.10.0-rc.5
 
 - **Bug Fix**
diff --git a/docs/modules/EitherT.ts.md b/docs/modules/EitherT.ts.md
index 5f25eb67..a8c78549 100644
--- a/docs/modules/EitherT.ts.md
+++ b/docs/modules/EitherT.ts.md
@@ -28,6 +28,7 @@ Added in v2.0.0
   - [map](#map)
   - [mapLeft](#mapleft)
   - [match](#match)
+  - [matchE](#matche)
   - [orElse](#orelse)
   - [right](#right)
   - [rightF](#rightf)
@@ -377,34 +378,64 @@ Added in v2.10.0
 **Signature**
 
 ```ts
-export declare function match<M extends URIS3>(
+export declare function match<F extends URIS3>(
+  F: Functor3<F>
+): <E, B, A>(
+  onLeft: (e: E) => B,
+  onRight: (a: A) => B
+) => <R, ME>(ma: Kind3<F, R, ME, Either<E, A>>) => Kind3<F, R, ME, B>
+export declare function match<F extends URIS3, FE>(
+  F: Functor3C<F, FE>
+): <E, B, A>(onLeft: (e: E) => B, onRight: (a: A) => B) => <R>(ma: Kind3<F, R, FE, Either<E, A>>) => Kind3<F, R, FE, B>
+export declare function match<F extends URIS2>(
+  F: Functor2<F>
+): <E, B, A>(onLeft: (e: E) => B, onRight: (a: A) => B) => <FE>(ma: Kind2<F, FE, Either<E, A>>) => Kind2<F, FE, B>
+export declare function match<F extends URIS2, FE>(
+  F: Functor2C<F, FE>
+): <E, B, A>(onLeft: (e: E) => B, onRight: (a: A) => B) => (ma: Kind2<F, FE, Either<E, A>>) => Kind2<F, FE, B>
+export declare function match<F extends URIS>(
+  F: Functor1<F>
+): <E, B, A>(onLeft: (e: E) => B, onRight: (a: A) => B) => (ma: Kind<F, Either<E, A>>) => Kind<F, B>
+export declare function match<F>(
+  F: Functor<F>
+): <E, B, A>(onLeft: (e: E) => B, onRight: (a: A) => B) => (ma: HKT<F, Either<E, A>>) => HKT<F, B>
+```
+
+Added in v3.0.0
+
+## matchE
+
+**Signature**
+
+```ts
+export declare function matchE<M extends URIS3>(
   M: Chain3<M>
 ): <E, R, FE, B, A>(
   onLeft: (e: E) => Kind3<M, R, FE, B>,
   onRight: (a: A) => Kind3<M, R, FE, B>
 ) => (ma: Kind3<M, R, FE, Either<E, A>>) => Kind3<M, R, FE, B>
-export declare function match<M extends URIS3, FE>(
+export declare function matchE<M extends URIS3, FE>(
   M: Chain3C<M, FE>
 ): <E, R, B, A>(
   onLeft: (e: E) => Kind3<M, R, FE, B>,
   onRight: (a: A) => Kind3<M, R, FE, B>
 ) => (ma: Kind3<M, R, FE, Either<E, A>>) => Kind3<M, R, FE, B>
-export declare function match<M extends URIS2>(
+export declare function matchE<M extends URIS2>(
   M: Chain2<M>
 ): <E, FE, B, A>(
   onLeft: (e: E) => Kind2<M, FE, B>,
   onRight: (a: A) => Kind2<M, FE, B>
 ) => (ma: Kind2<M, FE, Either<E, A>>) => Kind2<M, FE, B>
-export declare function match<M extends URIS2, FE>(
+export declare function matchE<M extends URIS2, FE>(
   M: Chain2C<M, FE>
 ): <E, B, A>(
   onLeft: (e: E) => Kind2<M, FE, B>,
   onRight: (a: A) => Kind2<M, FE, B>
 ) => (ma: Kind2<M, FE, Either<E, A>>) => Kind2<M, FE, B>
-export declare function match<M extends URIS>(
+export declare function matchE<M extends URIS>(
   M: Chain1<M>
 ): <E, B, A>(onLeft: (e: E) => Kind<M, B>, onRight: (a: A) => Kind<M, B>) => (ma: Kind<M, Either<E, A>>) => Kind<M, B>
-export declare function match<M>(
+export declare function matchE<M>(
   M: Chain<M>
 ): <E, B, A>(onLeft: (e: E) => HKT<M, B>, onRight: (a: A) => HKT<M, B>) => (ma: HKT<M, Either<E, A>>) => HKT<M, B>
 ```
diff --git a/docs/modules/IOEither.ts.md b/docs/modules/IOEither.ts.md
index 03922cd5..df6a7566 100644
--- a/docs/modules/IOEither.ts.md
+++ b/docs/modules/IOEither.ts.md
@@ -68,6 +68,8 @@ Added in v2.0.0
   - [getOrElse](#getorelse)
   - [getOrElseW](#getorelsew)
   - [match](#match)
+  - [matchE](#matche)
+  - [matchEW](#matchew)
   - [matchW](#matchw)
 - [instances](#instances)
   - [Alt](#alt-1)
@@ -594,7 +596,7 @@ Added in v2.0.0
 
 ## fold
 
-Alias of [`match`](#match).
+Alias of [`matchE`](#matchE).
 
 **Signature**
 
@@ -609,7 +611,7 @@ Added in v2.0.0
 
 ## foldW
 
-Alias of [`matchW`](#matchW).
+Alias of [`matchEW`](#matchEW).
 
 **Signature**
 
@@ -649,7 +651,17 @@ Added in v2.6.0
 **Signature**
 
 ```ts
-export declare const match: <E, A, B>(
+export declare const match: <E, B, A>(onLeft: (e: E) => B, onRight: (a: A) => B) => (ma: IOEither<E, A>) => I.IO<B>
+```
+
+Added in v2.10.0
+
+## matchE
+
+**Signature**
+
+```ts
+export declare const matchE: <E, A, B>(
   onLeft: (e: E) => I.IO<B>,
   onRight: (a: A) => I.IO<B>
 ) => (ma: IOEither<E, A>) => I.IO<B>
@@ -657,6 +669,21 @@ export declare const match: <E, A, B>(
 
 Added in v2.10.0
 
+## matchEW
+
+Less strict version of [`matchE`](#matchE).
+
+**Signature**
+
+```ts
+export declare const matchEW: <E, B, A, C>(
+  onLeft: (e: E) => I.IO<B>,
+  onRight: (a: A) => I.IO<C>
+) => (ma: IOEither<E, A>) => I.IO<B | C>
+```
+
+Added in v2.10.0
+
 ## matchW
 
 Less strict version of [`match`](#match).
@@ -665,8 +692,8 @@ Less strict version of [`match`](#match).
 
 ```ts
 export declare const matchW: <E, B, A, C>(
-  onLeft: (e: E) => I.IO<B>,
-  onRight: (a: A) => I.IO<C>
+  onLeft: (e: E) => B,
+  onRight: (a: A) => C
 ) => (ma: IOEither<E, A>) => I.IO<B | C>
 ```
 
diff --git a/docs/modules/OptionT.ts.md b/docs/modules/OptionT.ts.md
index 46f20254..aaa6f805 100644
--- a/docs/modules/OptionT.ts.md
+++ b/docs/modules/OptionT.ts.md
@@ -31,6 +31,7 @@ Added in v2.0.0
   - [getOrElse](#getorelse)
   - [map](#map)
   - [match](#match)
+  - [matchE](#matche)
   - [some](#some)
   - [zero](#zero)
   - [~~OptionM1~~ (interface)](#optionm1-interface)
@@ -504,40 +505,70 @@ Added in v2.10.0
 **Signature**
 
 ```ts
-export declare function match<M extends URIS4>(
+export declare function match<F extends URIS4>(
+  F: Functor4<F>
+): <B, A>(onNone: () => B, onSome: (a: A) => B) => <S, R, E>(ma: Kind4<F, S, R, E, Option<A>>) => Kind4<F, S, R, E, B>
+export declare function match<F extends URIS3>(
+  F: Functor3<F>
+): <B, A>(onNone: () => B, onSome: (a: A) => B) => <R, E>(ma: Kind3<F, R, E, Option<A>>) => Kind3<F, R, E, B>
+export declare function match<F extends URIS3, E>(
+  F: Functor3C<F, E>
+): <B, A>(onNone: () => B, onSome: (a: A) => B) => <R>(ma: Kind3<F, R, E, Option<A>>) => Kind3<F, R, E, B>
+export declare function match<F extends URIS2>(
+  F: Functor2<F>
+): <B, A>(onNone: () => B, onSome: (a: A) => B) => <E>(ma: Kind2<F, E, Option<A>>) => Kind2<F, E, B>
+export declare function match<F extends URIS2, E>(
+  F: Functor2C<F, E>
+): <B, A>(onNone: () => B, onSome: (a: A) => B) => (ma: Kind2<F, E, Option<A>>) => Kind2<F, E, B>
+export declare function match<F extends URIS>(
+  F: Functor1<F>
+): <B, A>(onNone: () => B, onSome: (a: A) => B) => (ma: Kind<F, Option<A>>) => Kind<F, B>
+export declare function match<F>(
+  F: Functor<F>
+): <B, A>(onNone: () => B, onSome: (a: A) => B) => (ma: HKT<F, Option<A>>) => HKT<F, B>
+```
+
+Added in v2.10.0
+
+## matchE
+
+**Signature**
+
+```ts
+export declare function matchE<M extends URIS4>(
   M: Chain4<M>
 ): <S, R, E, B, A>(
   onNone: () => Kind4<M, S, R, E, B>,
   onSome: (a: A) => Kind4<M, S, R, E, B>
 ) => (ma: Kind4<M, S, R, E, Option<A>>) => Kind4<M, S, R, E, B>
-export declare function match<M extends URIS3>(
+export declare function matchE<M extends URIS3>(
   M: Chain3<M>
 ): <R, E, B, A>(
   onNone: () => Kind3<M, R, E, B>,
   onSome: (a: A) => Kind3<M, R, E, B>
 ) => (ma: Kind3<M, R, E, Option<A>>) => Kind3<M, R, E, B>
-export declare function match<M extends URIS3, E>(
+export declare function matchE<M extends URIS3, E>(
   M: Chain3C<M, E>
 ): <R, B, A>(
   onNone: () => Kind3<M, R, E, B>,
   onSome: (a: A) => Kind3<M, R, E, B>
 ) => (ma: Kind3<M, R, E, Option<A>>) => Kind3<M, R, E, B>
-export declare function match<M extends URIS2>(
+export declare function matchE<M extends URIS2>(
   M: Chain2<M>
 ): <E, B, A>(
   onNone: () => Kind2<M, E, B>,
   onSome: (a: A) => Kind2<M, E, B>
 ) => (ma: Kind2<M, E, Option<A>>) => Kind2<M, E, B>
-export declare function match<M extends URIS2, E>(
+export declare function matchE<M extends URIS2, E>(
   M: Chain2C<M, E>
 ): <B, A>(
   onNone: () => Kind2<M, E, B>,
   onSome: (a: A) => Kind2<M, E, B>
 ) => (ma: Kind2<M, E, Option<A>>) => Kind2<M, E, B>
-export declare function match<M extends URIS>(
+export declare function matchE<M extends URIS>(
   M: Chain1<M>
 ): <B, A>(onNone: () => Kind<M, B>, onSome: (a: A) => Kind<M, B>) => (ma: Kind<M, Option<A>>) => Kind<M, B>
-export declare function match<M>(
+export declare function matchE<M>(
   M: Chain<M>
 ): <B, A>(onNone: () => HKT<M, B>, onSome: (a: A) => HKT<M, B>) => (ma: HKT<M, Option<A>>) => HKT<M, B>
 ```
diff --git a/docs/modules/ReaderEither.ts.md b/docs/modules/ReaderEither.ts.md
index 26885f05..5038cb62 100644
--- a/docs/modules/ReaderEither.ts.md
+++ b/docs/modules/ReaderEither.ts.md
@@ -64,6 +64,8 @@ Added in v2.0.0
   - [getOrElse](#getorelse)
   - [getOrElseW](#getorelsew)
   - [match](#match)
+  - [matchE](#matche)
+  - [matchEW](#matchew)
   - [matchW](#matchw)
 - [instances](#instances)
   - [Alt](#alt-1)
@@ -593,7 +595,7 @@ Added in v2.0.0
 
 ## fold
 
-Alias of [`match`](#match).
+Alias of [`matchE`](#matchE).
 
 **Signature**
 
@@ -608,7 +610,7 @@ Added in v2.0.0
 
 ## foldW
 
-Alias of [`matchW`](#matchW).
+Alias of [`matchEW`](#matchEW).
 
 **Signature**
 
@@ -652,7 +654,20 @@ Added in v2.6.0
 **Signature**
 
 ```ts
-export declare const match: <R, E, A, B>(
+export declare const match: <E, B, A>(
+  onLeft: (e: E) => B,
+  onRight: (a: A) => B
+) => <R>(ma: ReaderEither<R, E, A>) => R.Reader<R, B>
+```
+
+Added in v2.10.0
+
+## matchE
+
+**Signature**
+
+```ts
+export declare const matchE: <R, E, A, B>(
   onLeft: (e: E) => R.Reader<R, B>,
   onRight: (a: A) => R.Reader<R, B>
 ) => (ma: ReaderEither<R, E, A>) => R.Reader<R, B>
@@ -660,14 +675,14 @@ export declare const match: <R, E, A, B>(
 
 Added in v2.10.0
 
-## matchW
+## matchEW
 
-Less strict version of [`match`](#match).
+Less strict version of [`matchE`](#matchE).
 
 **Signature**
 
 ```ts
-export declare const matchW: <E, R2, B, A, R3, C>(
+export declare const matchEW: <E, R2, B, A, R3, C>(
   onLeft: (e: E) => R.Reader<R2, B>,
   onRight: (a: A) => R.Reader<R3, C>
 ) => <R1>(ma: ReaderEither<R1, E, A>) => R.Reader<R1 & R2 & R3, B | C>
@@ -675,6 +690,21 @@ export declare const matchW: <E, R2, B, A, R3, C>(
 
 Added in v2.10.0
 
+## matchW
+
+Less strict version of [`match`](#match).
+
+**Signature**
+
+```ts
+export declare const matchW: <E, B, A, C>(
+  onLeft: (e: E) => B,
+  onRight: (a: A) => C
+) => <R>(ma: R.Reader<R, E.Either<E, A>>) => R.Reader<R, B | C>
+```
+
+Added in v2.10.0
+
 # instances
 
 ## Alt
diff --git a/docs/modules/ReaderTaskEither.ts.md b/docs/modules/ReaderTaskEither.ts.md
index c104aab6..16a0839e 100644
--- a/docs/modules/ReaderTaskEither.ts.md
+++ b/docs/modules/ReaderTaskEither.ts.md
@@ -87,6 +87,8 @@ Added in v2.0.0
   - [getOrElse](#getorelse)
   - [getOrElseW](#getorelsew)
   - [match](#match)
+  - [matchE](#matche)
+  - [matchEW](#matchew)
   - [matchW](#matchw)
 - [instances](#instances)
   - [Alt](#alt-1)
@@ -890,7 +892,7 @@ Added in v2.0.0
 
 ## fold
 
-Alias of [`match`](#match).
+Alias of [`matchE`](#matchE).
 
 **Signature**
 
@@ -905,7 +907,7 @@ Added in v2.0.0
 
 ## foldW
 
-Alias of [`matchW`](#matchW).
+Alias of [`matchEW`](#matchEW).
 
 **Signature**
 
@@ -949,7 +951,20 @@ Added in v2.6.0
 **Signature**
 
 ```ts
-export declare const match: <R, E, A, B>(
+export declare const match: <E, B, A>(
+  onLeft: (e: E) => B,
+  onRight: (a: A) => B
+) => <R>(ma: ReaderTaskEither<R, E, A>) => RT.ReaderTask<R, B>
+```
+
+Added in v2.10.0
+
+## matchE
+
+**Signature**
+
+```ts
+export declare const matchE: <R, E, A, B>(
   onLeft: (e: E) => RT.ReaderTask<R, B>,
   onRight: (a: A) => RT.ReaderTask<R, B>
 ) => (ma: ReaderTaskEither<R, E, A>) => RT.ReaderTask<R, B>
@@ -957,14 +972,14 @@ export declare const match: <R, E, A, B>(
 
 Added in v2.10.0
 
-## matchW
+## matchEW
 
-Less strict version of [`match`](#match).
+Less strict version of [`matchE`](#matchE).
 
 **Signature**
 
 ```ts
-export declare const matchW: <E, R2, B, A, R3, C>(
+export declare const matchEW: <E, R2, B, A, R3, C>(
   onLeft: (e: E) => RT.ReaderTask<R2, B>,
   onRight: (a: A) => RT.ReaderTask<R3, C>
 ) => <R1>(ma: ReaderTaskEither<R1, E, A>) => RT.ReaderTask<R1 & R2 & R3, B | C>
@@ -972,6 +987,21 @@ export declare const matchW: <E, R2, B, A, R3, C>(
 
 Added in v2.10.0
 
+## matchW
+
+Less strict version of [`match`](#match).
+
+**Signature**
+
+```ts
+export declare const matchW: <E, B, A, C>(
+  onLeft: (e: E) => B,
+  onRight: (a: A) => C
+) => <R>(ma: ReaderTaskEither<R, E, A>) => RT.ReaderTask<R, B | C>
+```
+
+Added in v2.10.0
+
 # instances
 
 ## Alt
diff --git a/docs/modules/TaskEither.ts.md b/docs/modules/TaskEither.ts.md
index 91a9346b..a83c4b1f 100644
--- a/docs/modules/TaskEither.ts.md
+++ b/docs/modules/TaskEither.ts.md
@@ -82,6 +82,8 @@ Added in v2.0.0
   - [getOrElse](#getorelse)
   - [getOrElseW](#getorelsew)
   - [match](#match)
+  - [matchE](#matche)
+  - [matchEW](#matchew)
   - [matchW](#matchw)
 - [instances](#instances)
   - [Alt](#alt-1)
@@ -780,7 +782,7 @@ Added in v2.0.0
 
 ## fold
 
-Alias of [`match`](#match).
+Alias of [`matchE`](#matchE).
 
 **Signature**
 
@@ -795,7 +797,7 @@ Added in v2.0.0
 
 ## foldW
 
-Alias of [`matchW`](#matchW).
+Alias of [`matchEW`](#matchEW).
 
 **Signature**
 
@@ -835,7 +837,17 @@ Added in v2.6.0
 **Signature**
 
 ```ts
-export declare const match: <E, A, B>(
+export declare const match: <E, B, A>(onLeft: (e: E) => B, onRight: (a: A) => B) => (ma: TaskEither<E, A>) => T.Task<B>
+```
+
+Added in v2.10.0
+
+## matchE
+
+**Signature**
+
+```ts
+export declare const matchE: <E, A, B>(
   onLeft: (e: E) => T.Task<B>,
   onRight: (a: A) => T.Task<B>
 ) => (ma: TaskEither<E, A>) => T.Task<B>
@@ -843,6 +855,21 @@ export declare const match: <E, A, B>(
 
 Added in v2.10.0
 
+## matchEW
+
+Less strict version of [`matchE`](#matchE).
+
+**Signature**
+
+```ts
+export declare const matchEW: <E, B, A, C>(
+  onLeft: (e: E) => T.Task<B>,
+  onRight: (a: A) => T.Task<C>
+) => (ma: TaskEither<E, A>) => T.Task<B | C>
+```
+
+Added in v2.10.0
+
 ## matchW
 
 Less strict version of [`match`](#match).
@@ -851,8 +878,8 @@ Less strict version of [`match`](#match).
 
 ```ts
 export declare const matchW: <E, B, A, C>(
-  onLeft: (e: E) => T.Task<B>,
-  onRight: (a: A) => T.Task<C>
+  onLeft: (e: E) => B,
+  onRight: (a: A) => C
 ) => (ma: TaskEither<E, A>) => T.Task<B | C>
 ```
 
diff --git a/docs/modules/TaskOption.ts.md b/docs/modules/TaskOption.ts.md
index fad6f6b6..a5e67aef 100644
--- a/docs/modules/TaskOption.ts.md
+++ b/docs/modules/TaskOption.ts.md
@@ -61,6 +61,8 @@ Added in v2.10.0
   - [getOrElse](#getorelse)
   - [getOrElseW](#getorelsew)
   - [match](#match)
+  - [matchE](#matche)
+  - [matchEW](#matchew)
   - [matchW](#matchw)
 - [instances](#instances)
   - [Alt](#alt-1)
@@ -487,7 +489,7 @@ Added in v2.10.0
 
 ## fold
 
-Alias of [`match`](#match).
+Alias of [`matchE`](#matchE).
 
 **Signature**
 
@@ -502,7 +504,7 @@ Added in v2.10.0
 
 ## foldW
 
-Alias of [`matchW`](#matchW).
+Alias of [`matchEW`](#matchEW).
 
 **Signature**
 
@@ -542,7 +544,17 @@ Added in v2.10.0
 **Signature**
 
 ```ts
-export declare const match: <B, A>(
+export declare const match: <B, A>(onNone: () => B, onSome: (a: A) => B) => (ma: TaskOption<A>) => T.Task<B>
+```
+
+Added in v2.10.0
+
+## matchE
+
+**Signature**
+
+```ts
+export declare const matchE: <B, A>(
   onNone: () => T.Task<B>,
   onSome: (a: A) => T.Task<B>
 ) => (ma: TaskOption<A>) => T.Task<B>
@@ -550,14 +562,14 @@ export declare const match: <B, A>(
 
 Added in v2.10.0
 
-## matchW
+## matchEW
 
-Less strict version of [`match`](#match).
+Less strict version of [`matchE`](#matchE).
 
 **Signature**
 
 ```ts
-export declare const matchW: <B, C, A>(
+export declare const matchEW: <B, C, A>(
   onNone: () => T.Task<B>,
   onSome: (a: A) => T.Task<C>
 ) => (ma: TaskOption<A>) => T.Task<B | C>
@@ -565,6 +577,18 @@ export declare const matchW: <B, C, A>(
 
 Added in v2.10.0
 
+## matchW
+
+Less strict version of [`match`](#match).
+
+**Signature**
+
+```ts
+export declare const matchW: <B, A, C>(onNone: () => B, onSome: (a: A) => C) => (ma: TaskOption<A>) => T.Task<B | C>
+```
+
+Added in v2.10.0
+
 # instances
 
 ## Alt
diff --git a/docs/modules/TaskThese.ts.md b/docs/modules/TaskThese.ts.md
index 00fa45c0..bdcb0a4e 100644
--- a/docs/modules/TaskThese.ts.md
+++ b/docs/modules/TaskThese.ts.md
@@ -43,6 +43,8 @@ Added in v2.4.0
   - [fold](#fold)
   - [foldW](#foldw)
   - [match](#match)
+  - [matchE](#matche)
+  - [matchEW](#matchew)
   - [matchW](#matchw)
 - [instances](#instances)
   - [Bifunctor](#bifunctor-1)
@@ -317,7 +319,7 @@ Added in v2.4.0
 
 ## fold
 
-Alias of [`match`](#match).
+Alias of [`matchE`](#matchE).
 
 **Signature**
 
@@ -333,7 +335,7 @@ Added in v2.4.0
 
 ## foldW
 
-Alias of [`matchW`](#matchW).
+Alias of [`matchEW`](#matchEW).
 
 **Signature**
 
@@ -353,6 +355,20 @@ Added in v2.10.0
 
 ```ts
 export declare const match: <E, B, A>(
+  onLeft: (e: E) => B,
+  onRight: (a: A) => B,
+  onBoth: (e: E, a: A) => B
+) => (fa: TaskThese<E, A>) => T.Task<B>
+```
+
+Added in v2.10.0
+
+## matchE
+
+**Signature**
+
+```ts
+export declare const matchE: <E, B, A>(
   onLeft: (e: E) => T.Task<B>,
   onRight: (a: A) => T.Task<B>,
   onBoth: (e: E, a: A) => T.Task<B>
@@ -361,14 +377,14 @@ export declare const match: <E, B, A>(
 
 Added in v2.10.0
 
-## matchW
+## matchEW
 
-Less strict version of [`match`](#match).
+Less strict version of [`matchE`](#matchE).
 
 **Signature**
 
 ```ts
-export declare const matchW: <E, B, A, C, D>(
+export declare const matchEW: <E, B, A, C, D>(
   onLeft: (e: E) => T.Task<B>,
   onRight: (a: A) => T.Task<C>,
   onBoth: (e: E, a: A) => T.Task<D>
@@ -377,6 +393,22 @@ export declare const matchW: <E, B, A, C, D>(
 
 Added in v2.10.0
 
+## matchW
+
+Less strict version of [`match`](#match).
+
+**Signature**
+
+```ts
+export declare const matchW: <E, B, A, C, D>(
+  onLeft: (e: E) => B,
+  onRight: (a: A) => C,
+  onBoth: (e: E, a: A) => D
+) => (ma: TaskThese<E, A>) => T.Task<B | C | D>
+```
+
+Added in v2.10.0
+
 # instances
 
 ## Bifunctor
diff --git a/docs/modules/TheseT.ts.md b/docs/modules/TheseT.ts.md
index 4a93d916..dbeeacdd 100644
--- a/docs/modules/TheseT.ts.md
+++ b/docs/modules/TheseT.ts.md
@@ -26,6 +26,7 @@ Added in v2.4.0
   - [map](#map)
   - [mapLeft](#mapleft)
   - [match](#match)
+  - [matchE](#matche)
   - [right](#right)
   - [rightF](#rightf)
   - [swap](#swap)
@@ -76,12 +77,6 @@ Added in v2.4.0
 **Signature**
 
 ```ts
-export declare function ap<F extends URIS4, E>(
-  F: Apply4<F>,
-  S: Semigroup<E>
-): <S, R, FE, A>(
-  fa: Kind4<F, S, R, FE, These<E, A>>
-) => <B>(fab: Kind4<F, S, R, FE, These<E, (a: A) => B>>) => Kind4<F, S, R, FE, These<E, B>>
 export declare function ap<F extends URIS3, E>(
   F: Apply3<F>,
   S: Semigroup<E>
@@ -119,12 +114,6 @@ Added in v2.10.0
 **Signature**
 
 ```ts
-export declare function bimap<F extends URIS4>(
-  F: Functor4<F>
-): <E, G, A, B>(
-  f: (e: E) => G,
-  g: (a: A) => B
-) => <S, R, FE>(fea: Kind4<F, S, R, FE, These<E, A>>) => Kind4<F, S, R, FE, These<G, B>>
 export declare function bimap<F extends URIS3>(
   F: Functor3<F>
 ): <E, G, A, B>(
@@ -158,9 +147,6 @@ Added in v2.10.0
 **Signature**
 
 ```ts
-export declare function both<F extends URIS4>(
-  F: Pointed4<F>
-): <E, A, S, R, FE>(e: E, a: A) => Kind4<F, S, R, FE, These<E, A>>
 export declare function both<F extends URIS3>(F: Pointed3<F>): <E, A, R, FE>(e: E, a: A) => Kind3<F, R, FE, These<E, A>>
 export declare function both<F extends URIS3, FE>(
   F: Pointed3C<F, FE>
@@ -178,12 +164,6 @@ Added in v2.10.0
 **Signature**
 
 ```ts
-export declare function chain<M extends URIS4, E>(
-  M: Monad4<M>,
-  S: Semigroup<E>
-): <A, S, R, ME, B>(
-  f: (a: A) => Kind4<M, S, R, ME, These<E, B>>
-) => (ma: Kind4<M, S, R, ME, These<E, A>>) => Kind4<M, S, R, ME, These<E, B>>
 export declare function chain<M extends URIS3, E>(
   M: Monad3<M>,
   S: Semigroup<E>
@@ -221,9 +201,6 @@ Added in v2.10.0
 **Signature**
 
 ```ts
-export declare function left<F extends URIS4>(
-  F: Pointed4<F>
-): <E, S, R, FE, A = never>(e: E) => Kind4<F, S, R, FE, These<E, A>>
 export declare function left<F extends URIS3>(
   F: Pointed3<F>
 ): <E, R, FE, A = never>(e: E) => Kind3<F, R, FE, These<E, A>>
@@ -245,9 +222,6 @@ Added in v2.10.0
 **Signature**
 
 ```ts
-export declare function leftF<F extends URIS4>(
-  F: Functor4<F>
-): <S, R, FE, E, A = never>(fe: Kind4<F, S, R, FE, E>) => Kind4<F, S, R, FE, These<E, A>>
 export declare function leftF<F extends URIS3>(
   F: Functor3<F>
 ): <R, FE, E, A = never>(fe: Kind3<F, R, FE, E>) => Kind3<F, R, FE, These<E, A>>
@@ -271,9 +245,6 @@ Added in v2.10.0
 **Signature**
 
 ```ts
-export declare function map<F extends URIS4>(
-  F: Functor4<F>
-): <A, B>(f: (a: A) => B) => <S, R, FE, E>(fa: Kind4<F, S, R, FE, These<E, A>>) => Kind4<F, S, R, FE, These<E, B>>
 export declare function map<F extends URIS3>(
   F: Functor3<F>
 ): <A, B>(f: (a: A) => B) => <R, FE, E>(fa: Kind3<F, R, FE, These<E, A>>) => Kind3<F, R, FE, These<E, B>>
@@ -301,9 +272,6 @@ Added in v2.10.0
 **Signature**
 
 ```ts
-export declare function mapLeft<F extends URIS4>(
-  F: Functor4<F>
-): <E, G>(f: (e: E) => G) => <S, R, FE, A>(fea: Kind4<F, S, R, FE, These<E, A>>) => Kind4<F, S, R, FE, These<G, A>>
 export declare function mapLeft<F extends URIS3>(
   F: Functor3<F>
 ): <E, G>(f: (e: E) => G) => <R, FE, A>(fea: Kind3<F, R, FE, These<E, A>>) => Kind3<F, R, FE, These<G, A>>
@@ -331,49 +299,93 @@ Added in v2.10.0
 **Signature**
 
 ```ts
-export declare function match<M extends URIS4>(
-  M: Chain4<M>
-): <E, S, R, ME, B, A>(
-  onLeft: (e: E) => Kind4<M, S, R, ME, B>,
-  onRight: (a: A) => Kind4<M, S, R, ME, B>,
-  onBoth: (e: E, a: A) => Kind4<M, S, R, ME, B>
-) => (ma: Kind4<M, S, R, ME, These<E, A>>) => Kind4<M, S, R, ME, B>
-export declare function match<M extends URIS3>(
+export declare function match<F extends URIS3>(
+  F: Functor3<F>
+): <E, B, A>(
+  onLeft: (e: E) => B,
+  onRight: (a: A) => B,
+  onBoth: (e: E, a: A) => B
+) => <S, R>(ma: Kind3<F, S, R, These<E, A>>) => Kind3<F, S, R, B>
+export declare function match<F extends URIS3, R>(
+  F: Functor3C<F, R>
+): <E, B, A>(
+  onLeft: (e: E) => B,
+  onRight: (a: A) => B,
+  onBoth: (e: E, a: A) => B
+) => <S>(ma: Kind3<F, S, R, These<E, A>>) => Kind3<F, S, R, B>
+export declare function match<F extends URIS2>(
+  F: Functor2<F>
+): <E, B, A>(
+  onLeft: (e: E) => B,
+  onRight: (a: A) => B,
+  onBoth: (e: E, a: A) => B
+) => <R>(ma: Kind2<F, R, These<E, A>>) => Kind2<F, R, B>
+export declare function match<M extends URIS2, R>(
+  F: Functor2C<M, R>
+): <E, B, A>(
+  onLeft: (e: E) => B,
+  onRight: (a: A) => B,
+  onBoth: (e: E, a: A) => B
+) => (ma: Kind2<M, R, These<E, A>>) => Kind2<M, R, B>
+export declare function match<F extends URIS>(
+  F: Functor1<F>
+): <E, B, A>(
+  onLeft: (e: E) => B,
+  onRight: (a: A) => B,
+  onBoth: (e: E, a: A) => B
+) => (ma: Kind<F, These<E, A>>) => Kind<F, B>
+export declare function match<F>(
+  F: Functor<F>
+): <E, B, A>(
+  onLeft: (e: E) => B,
+  onRight: (a: A) => B,
+  onBoth: (e: E, a: A) => B
+) => (ma: HKT<F, These<E, A>>) => HKT<F, B>
+```
+
+Added in v2.10.0
+
+## matchE
+
+**Signature**
+
+```ts
+export declare function matchE<M extends URIS3>(
   M: Chain3<M>
 ): <E, R, ME, B, A>(
   onLeft: (e: E) => Kind3<M, R, ME, B>,
   onRight: (a: A) => Kind3<M, R, ME, B>,
   onBoth: (e: E, a: A) => Kind3<M, R, ME, B>
 ) => (ma: Kind3<M, R, ME, These<E, A>>) => Kind3<M, R, ME, B>
-export declare function match<M extends URIS3, ME>(
+export declare function matchE<M extends URIS3, ME>(
   M: Chain3C<M, ME>
 ): <E, R, B, A>(
   onLeft: (e: E) => Kind3<M, R, ME, B>,
   onRight: (a: A) => Kind3<M, R, ME, B>,
   onBoth: (e: E, a: A) => Kind3<M, R, ME, B>
 ) => (ma: Kind3<M, R, ME, These<E, A>>) => Kind3<M, R, ME, B>
-export declare function match<M extends URIS2>(
+export declare function matchE<M extends URIS2>(
   M: Chain2<M>
 ): <E, ME, B, A>(
   onLeft: (e: E) => Kind2<M, ME, B>,
   onRight: (a: A) => Kind2<M, ME, B>,
   onBoth: (e: E, a: A) => Kind2<M, ME, B>
 ) => (ma: Kind2<M, ME, These<E, A>>) => Kind2<M, ME, B>
-export declare function match<M extends URIS2, ME>(
+export declare function matchE<M extends URIS2, ME>(
   M: Chain2C<M, ME>
 ): <E, B, A>(
   onLeft: (e: E) => Kind2<M, ME, B>,
   onRight: (a: A) => Kind2<M, ME, B>,
   onBoth: (e: E, a: A) => Kind2<M, ME, B>
 ) => (ma: Kind2<M, ME, These<E, A>>) => Kind2<M, ME, B>
-export declare function match<M extends URIS>(
+export declare function matchE<M extends URIS>(
   M: Chain1<M>
 ): <E, B, A>(
   onLeft: (e: E) => Kind<M, B>,
   onRight: (a: A) => Kind<M, B>,
   onBoth: (e: E, a: A) => Kind<M, B>
 ) => (ma: Kind<M, These<E, A>>) => Kind<M, B>
-export declare function match<M>(
+export declare function matchE<M>(
   M: Chain<M>
 ): <E, B, A>(
   onLeft: (e: E) => HKT<M, B>,
@@ -389,9 +401,6 @@ Added in v2.10.0
 **Signature**
 
 ```ts
-export declare function right<F extends URIS4>(
-  F: Pointed4<F>
-): <A, S, R, FE, E = never>(a: A) => Kind4<F, S, R, FE, These<E, A>>
 export declare function right<F extends URIS3>(
   F: Pointed3<F>
 ): <A, R, FE, E = never>(a: A) => Kind3<F, R, FE, These<E, A>>
@@ -413,9 +422,6 @@ Added in v2.10.0
 **Signature**
 
 ```ts
-export declare function rightF<F extends URIS4>(
-  F: Functor4<F>
-): <S, R, FE, A, E = never>(fa: Kind4<F, S, R, FE, A>) => Kind4<F, S, R, FE, These<E, A>>
 export declare function rightF<F extends URIS3>(
   F: Functor3<F>
 ): <R, FE, A, E = never>(fa: Kind3<F, R, FE, A>) => Kind3<F, R, FE, These<E, A>>
@@ -439,9 +445,6 @@ Added in v2.10.0
 **Signature**
 
 ```ts
-export declare function swap<F extends URIS4>(
-  F: Functor4<F>
-): <S, R, FE, E, A>(ma: Kind4<F, S, R, FE, These<E, A>>) => Kind4<F, S, R, FE, These<A, E>>
 export declare function swap<F extends URIS3>(
   F: Functor3<F>
 ): <R, FE, E, A>(ma: Kind3<F, R, FE, These<E, A>>) => Kind3<F, R, FE, These<A, E>>
@@ -465,12 +468,6 @@ Added in v2.10.0
 **Signature**
 
 ```ts
-export declare function toTuple2<F extends URIS4>(
-  F: Functor4<F>
-): <E, A>(
-  e: Lazy<E>,
-  a: Lazy<A>
-) => <S, R, FE>(fa: Kind4<F, S, R, FE, These<E, A>>) => Kind4<F, S, R, FE, readonly [E, A]>
 export declare function toTuple2<F extends URIS3>(
   F: Functor3<F>
 ): <E, A>(e: Lazy<E>, a: Lazy<A>) => <R, FE>(fa: Kind3<F, R, FE, These<E, A>>) => Kind3<F, R, FE, readonly [E, A]>
diff --git a/package-lock.json b/package-lock.json
index 2dad4e58..d245bf8c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "fp-ts",
-  "version": "2.10.0-rc.5",
+  "version": "2.10.0-rc.6",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
diff --git a/package.json b/package.json
index 093a2ff1..d929abf2 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "fp-ts",
-  "version": "2.10.0-rc.5",
+  "version": "2.10.0-rc.6",
   "description": "Functional programming in TypeScript",
   "main": "lib/index.js",
   "module": "es6/index.js",
diff --git a/src/EitherT.ts b/src/EitherT.ts
index b2b45017..8e26b44f 100644
--- a/src/EitherT.ts
+++ b/src/EitherT.ts
@@ -14,6 +14,10 @@ import { Semigroup } from './Semigroup'
 
 import Either = E.Either
 
+// -------------------------------------------------------------------------------------
+// constructors
+// -------------------------------------------------------------------------------------
+
 /**
  * @since 2.10.0
  */
@@ -84,6 +88,10 @@ export function leftF<F>(F: Functor<F>): <E, A = never>(fe: HKT<F, E>) => HKT<F,
   return (fe) => F.map(fe, E.left)
 }
 
+// -------------------------------------------------------------------------------------
+// type class members
+// -------------------------------------------------------------------------------------
+
 /**
  * @since 2.10.0
  */
@@ -271,37 +279,122 @@ export function mapLeft<F>(
 /**
  * @since 2.10.0
  */
-export function match<M extends URIS3>(
+export function altValidation<M extends URIS3, E>(
+  M: Monad3<M>,
+  S: Semigroup<E>
+): <R, ME, A>(
+  second: Lazy<Kind3<M, R, ME, Either<E, A>>>
+) => (first: Kind3<M, R, ME, Either<E, A>>) => Kind3<M, R, ME, Either<E, A>>
+export function altValidation<M extends URIS3, ME, E>(
+  M: Monad3C<M, ME>,
+  S: Semigroup<E>
+): <R, A>(
+  second: Lazy<Kind3<M, R, ME, Either<E, A>>>
+) => (first: Kind3<M, R, ME, Either<E, A>>) => Kind3<M, R, ME, Either<E, A>>
+export function altValidation<M extends URIS2, E>(
+  M: Monad2<M>,
+  S: Semigroup<E>
+): <ME, A>(
+  second: Lazy<Kind2<M, ME, Either<E, A>>>
+) => (first: Kind2<M, ME, Either<E, A>>) => Kind2<M, ME, Either<E, A>>
+export function altValidation<M extends URIS2, ME, E>(
+  M: Monad2C<M, ME>,
+  S: Semigroup<E>
+): <A>(second: Lazy<Kind2<M, ME, Either<E, A>>>) => (first: Kind2<M, ME, Either<E, A>>) => Kind2<M, ME, Either<E, A>>
+export function altValidation<M extends URIS, E>(
+  M: Monad1<M>,
+  S: Semigroup<E>
+): <A>(second: Lazy<Kind<M, Either<E, A>>>) => (first: Kind<M, Either<E, A>>) => Kind<M, Either<E, A>>
+export function altValidation<M, E>(
+  M: Monad<M>,
+  S: Semigroup<E>
+): <A>(second: Lazy<HKT<M, Either<E, A>>>) => (first: HKT<M, Either<E, A>>) => HKT<M, Either<E, A>>
+export function altValidation<M, E>(
+  M: Monad<M>,
+  S: Semigroup<E>
+): <A>(second: Lazy<HKT<M, Either<E, A>>>) => (first: HKT<M, Either<E, A>>) => HKT<M, Either<E, A>> {
+  return (second) => (first) =>
+    M.chain(
+      first,
+      E.match(
+        (e1) =>
+          M.map(
+            second(),
+            E.mapLeft((e2) => S.concat(e1, e2))
+          ),
+        right(M)
+      )
+    )
+}
+
+// -------------------------------------------------------------------------------------
+// destructors
+// -------------------------------------------------------------------------------------
+
+/**
+ * @since 3.0.0
+ */
+export function match<F extends URIS3>(
+  F: Functor3<F>
+): <E, B, A>(
+  onLeft: (e: E) => B,
+  onRight: (a: A) => B
+) => <R, ME>(ma: Kind3<F, R, ME, Either<E, A>>) => Kind3<F, R, ME, B>
+export function match<F extends URIS3, FE>(
+  F: Functor3C<F, FE>
+): <E, B, A>(onLeft: (e: E) => B, onRight: (a: A) => B) => <R>(ma: Kind3<F, R, FE, Either<E, A>>) => Kind3<F, R, FE, B>
+export function match<F extends URIS2>(
+  F: Functor2<F>
+): <E, B, A>(onLeft: (e: E) => B, onRight: (a: A) => B) => <FE>(ma: Kind2<F, FE, Either<E, A>>) => Kind2<F, FE, B>
+export function match<F extends URIS2, FE>(
+  F: Functor2C<F, FE>
+): <E, B, A>(onLeft: (e: E) => B, onRight: (a: A) => B) => (ma: Kind2<F, FE, Either<E, A>>) => Kind2<F, FE, B>
+export function match<F extends URIS>(
+  F: Functor1<F>
+): <E, B, A>(onLeft: (e: E) => B, onRight: (a: A) => B) => (ma: Kind<F, Either<E, A>>) => Kind<F, B>
+export function match<F>(
+  F: Functor<F>
+): <E, B, A>(onLeft: (e: E) => B, onRight: (a: A) => B) => (ma: HKT<F, Either<E, A>>) => HKT<F, B>
+export function match<F>(
+  F: Functor<F>
+): <E, B, A>(onLeft: (e: E) => B, onRight: (a: A) => B) => (ma: HKT<F, Either<E, A>>) => HKT<F, B> {
+  return (onLeft, onRight) => (ma) => F.map(ma, E.match(onLeft, onRight))
+}
+
+/**
+ * @since 2.10.0
+ */
+export function matchE<M extends URIS3>(
   M: Chain3<M>
 ): <E, R, FE, B, A>(
   onLeft: (e: E) => Kind3<M, R, FE, B>,
   onRight: (a: A) => Kind3<M, R, FE, B>
 ) => (ma: Kind3<M, R, FE, Either<E, A>>) => Kind3<M, R, FE, B>
-export function match<M extends URIS3, FE>(
+export function matchE<M extends URIS3, FE>(
   M: Chain3C<M, FE>
 ): <E, R, B, A>(
   onLeft: (e: E) => Kind3<M, R, FE, B>,
   onRight: (a: A) => Kind3<M, R, FE, B>
 ) => (ma: Kind3<M, R, FE, Either<E, A>>) => Kind3<M, R, FE, B>
-export function match<M extends URIS2>(
+export function matchE<M extends URIS2>(
   M: Chain2<M>
 ): <E, FE, B, A>(
   onLeft: (e: E) => Kind2<M, FE, B>,
   onRight: (a: A) => Kind2<M, FE, B>
 ) => (ma: Kind2<M, FE, Either<E, A>>) => Kind2<M, FE, B>
-export function match<M extends URIS2, FE>(
+export function matchE<M extends URIS2, FE>(
   M: Chain2C<M, FE>
 ): <E, B, A>(
   onLeft: (e: E) => Kind2<M, FE, B>,
   onRight: (a: A) => Kind2<M, FE, B>
 ) => (ma: Kind2<M, FE, Either<E, A>>) => Kind2<M, FE, B>
-export function match<M extends URIS>(
+export function matchE<M extends URIS>(
   M: Chain1<M>
 ): <E, B, A>(onLeft: (e: E) => Kind<M, B>, onRight: (a: A) => Kind<M, B>) => (ma: Kind<M, Either<E, A>>) => Kind<M, B>
-export function match<M>(
+export function matchE<M>(
   M: Chain<M>
 ): <E, B, A>(onLeft: (e: E) => HKT<M, B>, onRight: (a: A) => HKT<M, B>) => (ma: HKT<M, Either<E, A>>) => HKT<M, B>
-export function match<M>(
+export function matchE<M>(
   M: Chain<M>
 ): <E, B, A>(onLeft: (e: E) => HKT<M, B>, onRight: (a: A) => HKT<M, B>) => (ma: HKT<M, Either<E, A>>) => HKT<M, B> {
   return (onLeft, onRight) => (ma) => M.chain(ma, E.match(onLeft, onRight))
@@ -334,6 +427,10 @@ export function getOrElse<M>(
   return (onLeft) => (ma) => M.chain(ma, E.match(onLeft, M.of))
 }
 
+// -------------------------------------------------------------------------------------
+// combinators
+// -------------------------------------------------------------------------------------
+
 /**
  * @since 2.10.0
  */
@@ -369,6 +466,10 @@ export function orElse<M>(
   return (onLeft) => (ma) => M.chain(ma, (e) => (E.isLeft(e) ? onLeft(e.left) : M.of(e)))
 }
 
+// -------------------------------------------------------------------------------------
+// utils
+// -------------------------------------------------------------------------------------
+
 /**
  * @since 2.10.0
  */
@@ -390,57 +491,6 @@ export function swap<F>(F: Functor<F>): <E, A>(ma: HKT<F, Either<E, A>>) => HKT<
   return (ma) => F.map(ma, E.swap)
 }
 
-/**
- * @since 2.10.0
- */
-export function altValidation<M extends URIS3, E>(
-  M: Monad3<M>,
-  S: Semigroup<E>
-): <R, ME, A>(
-  second: Lazy<Kind3<M, R, ME, Either<E, A>>>
-) => (first: Kind3<M, R, ME, Either<E, A>>) => Kind3<M, R, ME, Either<E, A>>
-export function altValidation<M extends URIS3, ME, E>(
-  M: Monad3C<M, ME>,
-  S: Semigroup<E>
-): <R, A>(
-  second: Lazy<Kind3<M, R, ME, Either<E, A>>>
-) => (first: Kind3<M, R, ME, Either<E, A>>) => Kind3<M, R, ME, Either<E, A>>
-export function altValidation<M extends URIS2, E>(
-  M: Monad2<M>,
-  S: Semigroup<E>
-): <ME, A>(
-  second: Lazy<Kind2<M, ME, Either<E, A>>>
-) => (first: Kind2<M, ME, Either<E, A>>) => Kind2<M, ME, Either<E, A>>
-export function altValidation<M extends URIS2, ME, E>(
-  M: Monad2C<M, ME>,
-  S: Semigroup<E>
-): <A>(second: Lazy<Kind2<M, ME, Either<E, A>>>) => (first: Kind2<M, ME, Either<E, A>>) => Kind2<M, ME, Either<E, A>>
-export function altValidation<M extends URIS, E>(
-  M: Monad1<M>,
-  S: Semigroup<E>
-): <A>(second: Lazy<Kind<M, Either<E, A>>>) => (first: Kind<M, Either<E, A>>) => Kind<M, Either<E, A>>
-export function altValidation<M, E>(
-  M: Monad<M>,
-  S: Semigroup<E>
-): <A>(second: Lazy<HKT<M, Either<E, A>>>) => (first: HKT<M, Either<E, A>>) => HKT<M, Either<E, A>>
-export function altValidation<M, E>(
-  M: Monad<M>,
-  S: Semigroup<E>
-): <A>(second: Lazy<HKT<M, Either<E, A>>>) => (first: HKT<M, Either<E, A>>) => HKT<M, Either<E, A>> {
-  return (second) => (first) =>
-    M.chain(
-      first,
-      E.match(
-        (e1) =>
-          M.map(
-            second(),
-            E.mapLeft((e2) => S.concat(e1, e2))
-          ),
-        right(M)
-      )
-    )
-}
-
 /**
  * @since 2.10.0
  */
@@ -575,7 +625,7 @@ export function getEitherM<M>(M: Monad<M>): EitherM<M> {
   const _alt = alt(M)
   const _bimap = bimap(M)
   const _mapLeft = mapLeft(M)
-  const _fold = match(M)
+  const _fold = matchE(M)
   const _getOrElse = getOrElse(M)
   const _orElse = orElse(M)
 
diff --git a/src/IOEither.ts b/src/IOEither.ts
index 28865fb8..70a551c3 100644
--- a/src/IOEither.ts
+++ b/src/IOEither.ts
@@ -116,36 +116,55 @@ export const fromIO: FromIO2<URI>['fromIO'] = rightIO
  * @category destructors
  * @since 2.10.0
  */
-export const match: <E, A, B>(onLeft: (e: E) => IO<B>, onRight: (a: A) => IO<B>) => (ma: IOEither<E, A>) => IO<B> =
+export const match: <E, B, A>(onLeft: (e: E) => B, onRight: (a: A) => B) => (ma: IOEither<E, A>) => IO<B> =
   /*#__PURE__*/
-  ET.match(I.Monad)
+  ET.match(I.Functor)
 
 /**
- * Alias of [`match`](#match).
+ * Less strict version of [`match`](#match).
+ *
+ * @category destructors
+ * @since 2.10.0
+ */
+export const matchW: <E, B, A, C>(
+  onLeft: (e: E) => B,
+  onRight: (a: A) => C
+) => (ma: IOEither<E, A>) => IO<B | C> = match as any
+
+/**
+ * @category destructors
+ * @since 2.10.0
+ */
+export const matchE: <E, A, B>(onLeft: (e: E) => IO<B>, onRight: (a: A) => IO<B>) => (ma: IOEither<E, A>) => IO<B> =
+  /*#__PURE__*/
+  ET.matchE(I.Monad)
+
+/**
+ * Alias of [`matchE`](#matchE).
  *
  * @category destructors
  * @since 2.0.0
  */
-export const fold = match
+export const fold = matchE
 
 /**
- * Less strict version of [`match`](#match).
+ * Less strict version of [`matchE`](#matchE).
  *
  * @category destructors
  * @since 2.10.0
  */
-export const matchW: <E, B, A, C>(
+export const matchEW: <E, B, A, C>(
   onLeft: (e: E) => IO<B>,
   onRight: (a: A) => IO<C>
-) => (ma: IOEither<E, A>) => IO<B | C> = match as any
+) => (ma: IOEither<E, A>) => IO<B | C> = matchE as any
 
 /**
- * Alias of [`matchW`](#matchW).
+ * Alias of [`matchEW`](#matchEW).
  *
  * @category destructors
  * @since 2.10.0
  */
-export const foldW = matchW
+export const foldW = matchEW
 
 /**
  * @category destructors
diff --git a/src/NonEmptyArray.ts b/src/NonEmptyArray.ts
index 46557882..c78720b4 100644
--- a/src/NonEmptyArray.ts
+++ b/src/NonEmptyArray.ts
@@ -25,9 +25,10 @@ import { identity, Lazy, pipe, Predicate, Refinement } from './function'
 import { bindTo as bindTo_, flap as flap_, Functor1 } from './Functor'
 import { FunctorWithIndex1 } from './FunctorWithIndex'
 import { HKT } from './HKT'
+import * as _ from './internal'
 import { Monad1 } from './Monad'
 import * as O from './Option'
-import { Ord, getMonoid } from './Ord'
+import { getMonoid, Ord } from './Ord'
 import { Pointed1 } from './Pointed'
 import * as RNEA from './ReadonlyNonEmptyArray'
 import * as Se from './Semigroup'
@@ -170,7 +171,8 @@ export const makeBy = <A>(n: number, f: (i: number) => A): NonEmptyArray<A> => {
  * @category constructors
  * @since 2.10.0
  */
-export const fromReadonlyNonEmptyArray = <A>(as: ReadonlyNonEmptyArray<A>): NonEmptyArray<A> => [as[0], ...as.slice(1)]
+export const fromReadonlyNonEmptyArray: <A>(as: ReadonlyNonEmptyArray<A>) => NonEmptyArray<A> =
+  _.fromReadonlyNonEmptyArray
 
 /**
  * Builds a `NonEmptyArray` from an `Array` returning `none` if `as` is an empty array
diff --git a/src/OptionT.ts b/src/OptionT.ts
index d4ba3290..a611aebe 100644
--- a/src/OptionT.ts
+++ b/src/OptionT.ts
@@ -318,43 +318,73 @@ export function fromEither<F>(F: Pointed<F>): <A>(e: Either<unknown, A>) => HKT<
 /**
  * @since 2.10.0
  */
-export function match<M extends URIS4>(
+export function match<F extends URIS4>(
+  F: Functor4<F>
+): <B, A>(onNone: () => B, onSome: (a: A) => B) => <S, R, E>(ma: Kind4<F, S, R, E, Option<A>>) => Kind4<F, S, R, E, B>
+export function match<F extends URIS3>(
+  F: Functor3<F>
+): <B, A>(onNone: () => B, onSome: (a: A) => B) => <R, E>(ma: Kind3<F, R, E, Option<A>>) => Kind3<F, R, E, B>
+export function match<F extends URIS3, E>(
+  F: Functor3C<F, E>
+): <B, A>(onNone: () => B, onSome: (a: A) => B) => <R>(ma: Kind3<F, R, E, Option<A>>) => Kind3<F, R, E, B>
+export function match<F extends URIS2>(
+  F: Functor2<F>
+): <B, A>(onNone: () => B, onSome: (a: A) => B) => <E>(ma: Kind2<F, E, Option<A>>) => Kind2<F, E, B>
+export function match<F extends URIS2, E>(
+  F: Functor2C<F, E>
+): <B, A>(onNone: () => B, onSome: (a: A) => B) => (ma: Kind2<F, E, Option<A>>) => Kind2<F, E, B>
+export function match<F extends URIS>(
+  F: Functor1<F>
+): <B, A>(onNone: () => B, onSome: (a: A) => B) => (ma: Kind<F, Option<A>>) => Kind<F, B>
+export function match<F>(
+  F: Functor<F>
+): <B, A>(onNone: () => B, onSome: (a: A) => B) => (ma: HKT<F, Option<A>>) => HKT<F, B>
+export function match<F>(
+  F: Functor<F>
+): <B, A>(onNone: () => B, onSome: (a: A) => B) => (ma: HKT<F, Option<A>>) => HKT<F, B> {
+  return (onNone, onSome) => (ma) => F.map(ma, O.match(onNone, onSome))
+}
+
+/**
+ * @since 2.10.0
+ */
+export function matchE<M extends URIS4>(
   M: Chain4<M>
 ): <S, R, E, B, A>(
   onNone: () => Kind4<M, S, R, E, B>,
   onSome: (a: A) => Kind4<M, S, R, E, B>
 ) => (ma: Kind4<M, S, R, E, Option<A>>) => Kind4<M, S, R, E, B>
-export function match<M extends URIS3>(
+export function matchE<M extends URIS3>(
   M: Chain3<M>
 ): <R, E, B, A>(
   onNone: () => Kind3<M, R, E, B>,
   onSome: (a: A) => Kind3<M, R, E, B>
 ) => (ma: Kind3<M, R, E, Option<A>>) => Kind3<M, R, E, B>
-export function match<M extends URIS3, E>(
+export function matchE<M extends URIS3, E>(
   M: Chain3C<M, E>
 ): <R, B, A>(
   onNone: () => Kind3<M, R, E, B>,
   onSome: (a: A) => Kind3<M, R, E, B>
 ) => (ma: Kind3<M, R, E, Option<A>>) => Kind3<M, R, E, B>
-export function match<M extends URIS2>(
+export function matchE<M extends URIS2>(
   M: Chain2<M>
 ): <E, B, A>(
   onNone: () => Kind2<M, E, B>,
   onSome: (a: A) => Kind2<M, E, B>
 ) => (ma: Kind2<M, E, Option<A>>) => Kind2<M, E, B>
-export function match<M extends URIS2, E>(
+export function matchE<M extends URIS2, E>(
   M: Chain2C<M, E>
 ): <B, A>(
   onNone: () => Kind2<M, E, B>,
   onSome: (a: A) => Kind2<M, E, B>
 ) => (ma: Kind2<M, E, Option<A>>) => Kind2<M, E, B>
-export function match<M extends URIS>(
+export function matchE<M extends URIS>(
   M: Chain1<M>
 ): <B, A>(onNone: () => Kind<M, B>, onSome: (a: A) => Kind<M, B>) => (ma: Kind<M, Option<A>>) => Kind<M, B>
-export function match<M>(
+export function matchE<M>(
   M: Chain<M>
 ): <B, A>(onNone: () => HKT<M, B>, onSome: (a: A) => HKT<M, B>) => (ma: HKT<M, Option<A>>) => HKT<M, B>
-export function match<M>(
+export function matchE<M>(
   M: Chain<M>
 ): <B, A>(onNone: () => HKT<M, B>, onSome: (a: A) => HKT<M, B>) => (ma: HKT<M, Option<A>>) => HKT<M, B> {
   return (onNone, onSome) => (ma) => M.chain(ma, O.match(onNone, onSome))
@@ -624,7 +654,7 @@ export function getOptionM<M>(M: Monad<M>): OptionM<M> {
   const mapM = map(M)
   const chainM = chain(M)
   const altM = alt(M)
-  const foldM = match(M)
+  const foldM = matchE(M)
   const getOrElseM = getOrElse(M)
   const zeroM = zero(M)
 
diff --git a/src/ReaderEither.ts b/src/ReaderEither.ts
index 05142b01..85dce395 100644
--- a/src/ReaderEither.ts
+++ b/src/ReaderEither.ts
@@ -117,39 +117,61 @@ export const fromEither: FromEither3<URI>['fromEither'] = R.of
  * @category destructors
  * @since 2.10.0
  */
-export const match: <R, E, A, B>(
+export const match: <E, B, A>(
+  onLeft: (e: E) => B,
+  onRight: (a: A) => B
+) => <R>(ma: ReaderEither<R, E, A>) => Reader<R, B> =
+  /*#__PURE__*/
+  ET.match(R.Functor)
+
+/**
+ * Less strict version of [`match`](#match).
+ *
+ * @category destructors
+ * @since 2.10.0
+ */
+export const matchW: <E, B, A, C>(
+  onLeft: (e: E) => B,
+  onRight: (a: A) => C
+) => <R>(ma: Reader<R, E.Either<E, A>>) => Reader<R, B | C> = match as any
+
+/**
+ * @category destructors
+ * @since 2.10.0
+ */
+export const matchE: <R, E, A, B>(
   onLeft: (e: E) => Reader<R, B>,
   onRight: (a: A) => Reader<R, B>
 ) => (ma: ReaderEither<R, E, A>) => Reader<R, B> =
   /*#__PURE__*/
-  ET.match(R.Monad)
+  ET.matchE(R.Monad)
 
 /**
- * Alias of [`match`](#match).
+ * Alias of [`matchE`](#matchE).
  *
  * @category destructors
  * @since 2.0.0
  */
-export const fold = match
+export const fold = matchE
 
 /**
- * Less strict version of [`match`](#match).
+ * Less strict version of [`matchE`](#matchE).
  *
  * @category destructors
  * @since 2.10.0
  */
-export const matchW: <E, R2, B, A, R3, C>(
+export const matchEW: <E, R2, B, A, R3, C>(
   onLeft: (e: E) => Reader<R2, B>,
   onRight: (a: A) => Reader<R3, C>
-) => <R1>(ma: ReaderEither<R1, E, A>) => Reader<R1 & R2 & R3, B | C> = match as any
+) => <R1>(ma: ReaderEither<R1, E, A>) => Reader<R1 & R2 & R3, B | C> = matchE as any
 
 /**
- * Alias of [`matchW`](#matchW).
+ * Alias of [`matchEW`](#matchEW).
  *
  * @category destructors
  * @since 2.10.0
  */
-export const foldW = matchW
+export const foldW = matchEW
 
 /**
  * @category destructors
diff --git a/src/ReaderTaskEither.ts b/src/ReaderTaskEither.ts
index 9c2e589b..c3671f45 100644
--- a/src/ReaderTaskEither.ts
+++ b/src/ReaderTaskEither.ts
@@ -220,39 +220,61 @@ export const fromEither: FromEither3<URI>['fromEither'] = RT.of
  * @category destructors
  * @since 2.10.0
  */
-export const match: <R, E, A, B>(
+export const match: <E, B, A>(
+  onLeft: (e: E) => B,
+  onRight: (a: A) => B
+) => <R>(ma: ReaderTaskEither<R, E, A>) => ReaderTask<R, B> =
+  /*#__PURE__*/
+  ET.match(RT.Functor)
+
+/**
+ * Less strict version of [`match`](#match).
+ *
+ * @category destructors
+ * @since 2.10.0
+ */
+export const matchW: <E, B, A, C>(
+  onLeft: (e: E) => B,
+  onRight: (a: A) => C
+) => <R>(ma: ReaderTaskEither<R, E, A>) => ReaderTask<R, B | C> = match as any
+
+/**
+ * @category destructors
+ * @since 2.10.0
+ */
+export const matchE: <R, E, A, B>(
   onLeft: (e: E) => ReaderTask<R, B>,
   onRight: (a: A) => ReaderTask<R, B>
 ) => (ma: ReaderTaskEither<R, E, A>) => ReaderTask<R, B> =
   /*#__PURE__*/
-  ET.match(RT.Chain)
+  ET.matchE(RT.Chain)
 
 /**
- * Alias of [`match`](#match).
+ * Alias of [`matchE`](#matchE).
  *
  * @category destructors
  * @since 2.0.0
  */
-export const fold = match
+export const fold = matchE
 
 /**
- * Less strict version of [`match`](#match).
+ * Less strict version of [`matchE`](#matchE).
  *
  * @category destructors
  * @since 2.10.0
  */
-export const matchW: <E, R2, B, A, R3, C>(
+export const matchEW: <E, R2, B, A, R3, C>(
   onLeft: (e: E) => ReaderTask<R2, B>,
   onRight: (a: A) => ReaderTask<R3, C>
-) => <R1>(ma: ReaderTaskEither<R1, E, A>) => ReaderTask<R1 & R2 & R3, B | C> = match as any
+) => <R1>(ma: ReaderTaskEither<R1, E, A>) => ReaderTask<R1 & R2 & R3, B | C> = matchE as any
 
 /**
- * Alias of [`matchW`](#matchW).
+ * Alias of [`matchEW`](#matchEW).
  *
  * @category destructors
  * @since 2.10.0
  */
-export const foldW = matchW
+export const foldW = matchEW
 
 /**
  * @category destructors
diff --git a/src/ReadonlyNonEmptyArray.ts b/src/ReadonlyNonEmptyArray.ts
index 5c0877fa..c6435df3 100644
--- a/src/ReadonlyNonEmptyArray.ts
+++ b/src/ReadonlyNonEmptyArray.ts
@@ -25,10 +25,11 @@ import { identity, Lazy, pipe, Predicate, Refinement } from './function'
 import { bindTo as bindTo_, flap as flap_, Functor1 } from './Functor'
 import { FunctorWithIndex1 } from './FunctorWithIndex'
 import { HKT } from './HKT'
+import * as _ from './internal'
 import { Monad1 } from './Monad'
-import { NonEmptyArray, fromReadonlyNonEmptyArray } from './NonEmptyArray'
+import { NonEmptyArray } from './NonEmptyArray'
 import * as O from './Option'
-import { Ord, getMonoid } from './Ord'
+import { getMonoid, Ord } from './Ord'
 import { Pointed1 } from './Pointed'
 import { ReadonlyRecord } from './ReadonlyRecord'
 import * as Se from './Semigroup'
@@ -85,7 +86,7 @@ export const append = <A>(end: A) => (init: ReadonlyArray<A>): ReadonlyNonEmptyA
  */
 export const unsafeInsertAt = <A>(i: number, a: A, as: ReadonlyArray<A>): ReadonlyNonEmptyArray<A> => {
   if (isNonEmpty(as)) {
-    const xs = fromReadonlyNonEmptyArray(as)
+    const xs = _.fromReadonlyNonEmptyArray(as)
     xs.splice(i, 0, a)
     return xs
   }
@@ -99,7 +100,7 @@ export const unsafeUpdateAt = <A>(i: number, a: A, as: ReadonlyNonEmptyArray<A>)
   if (as[i] === a) {
     return as
   } else {
-    const xs = fromReadonlyNonEmptyArray(as)
+    const xs = _.fromReadonlyNonEmptyArray(as)
     xs[i] = a
     return xs
   }
@@ -464,7 +465,7 @@ export const intersperse = <A>(middle: A) => (as: ReadonlyNonEmptyArray<A>): Rea
 export const chainWithIndex = <A, B>(f: (i: number, a: A) => ReadonlyNonEmptyArray<B>) => (
   as: ReadonlyNonEmptyArray<A>
 ): ReadonlyNonEmptyArray<B> => {
-  const out: NonEmptyArray<B> = fromReadonlyNonEmptyArray(f(0, head(as)))
+  const out: NonEmptyArray<B> = _.fromReadonlyNonEmptyArray(f(0, head(as)))
   for (let i = 1; i < as.length; i++) {
     out.push(...f(i, as[i]))
   }
diff --git a/src/TaskEither.ts b/src/TaskEither.ts
index f8c642fb..a3210be1 100644
--- a/src/TaskEither.ts
+++ b/src/TaskEither.ts
@@ -158,39 +158,58 @@ export const fromTask: FromTask2<URI>['fromTask'] = rightTask
  * @category destructors
  * @since 2.10.0
  */
-export const match: <E, A, B>(
+export const match: <E, B, A>(onLeft: (e: E) => B, onRight: (a: A) => B) => (ma: TaskEither<E, A>) => Task<B> =
+  /*#__PURE__*/
+  ET.match(T.Functor)
+
+/**
+ * Less strict version of [`match`](#match).
+ *
+ * @category destructors
+ * @since 2.10.0
+ */
+export const matchW: <E, B, A, C>(
+  onLeft: (e: E) => B,
+  onRight: (a: A) => C
+) => (ma: TaskEither<E, A>) => Task<B | C> = match as any
+
+/**
+ * @category destructors
+ * @since 2.10.0
+ */
+export const matchE: <E, A, B>(
   onLeft: (e: E) => Task<B>,
   onRight: (a: A) => Task<B>
 ) => (ma: TaskEither<E, A>) => Task<B> =
   /*#__PURE__*/
-  ET.match(T.Monad)
+  ET.matchE(T.Monad)
 
 /**
- * Alias of [`match`](#match).
+ * Alias of [`matchE`](#matchE).
  *
  * @category destructors
  * @since 2.0.0
  */
-export const fold = match
+export const fold = matchE
 
 /**
- * Less strict version of [`match`](#match).
+ * Less strict version of [`matchE`](#matchE).
  *
  * @category destructors
  * @since 2.10.0
  */
-export const matchW: <E, B, A, C>(
+export const matchEW: <E, B, A, C>(
   onLeft: (e: E) => Task<B>,
   onRight: (a: A) => Task<C>
-) => (ma: TaskEither<E, A>) => Task<B | C> = match as any
+) => (ma: TaskEither<E, A>) => Task<B | C> = matchE as any
 
 /**
- * Alias of [`matchW`](#matchW).
+ * Alias of [`matchEW`](#matchEW).
  *
  * @category destructors
  * @since 2.10.0
  */
-export const foldW = matchW
+export const foldW = matchEW
 
 /**
  * @category destructors
diff --git a/src/TaskOption.ts b/src/TaskOption.ts
index a57ba65e..1e1e567c 100644
--- a/src/TaskOption.ts
+++ b/src/TaskOption.ts
@@ -105,36 +105,55 @@ export const fromTask: FromTask1<URI>['fromTask'] =
  * @category destructors
  * @since 2.10.0
  */
-export const match: <B, A>(onNone: () => Task<B>, onSome: (a: A) => Task<B>) => (ma: TaskOption<A>) => Task<B> =
+export const match: <B, A>(onNone: () => B, onSome: (a: A) => B) => (ma: TaskOption<A>) => Task<B> =
   /*#__PURE__*/
-  OT.match(T.Chain)
+  OT.match(T.Functor)
 
 /**
- * Alias of [`match`](#match).
+ * Less strict version of [`match`](#match).
  *
  * @category destructors
  * @since 2.10.0
  */
-export const fold = match
+export const matchW: <B, A, C>(
+  onNone: () => B,
+  onSome: (a: A) => C
+) => (ma: TaskOption<A>) => Task<B | C> = match as any
 
 /**
- * Less strict version of [`match`](#match).
+ * @category destructors
+ * @since 2.10.0
+ */
+export const matchE: <B, A>(onNone: () => Task<B>, onSome: (a: A) => Task<B>) => (ma: TaskOption<A>) => Task<B> =
+  /*#__PURE__*/
+  OT.matchE(T.Chain)
+
+/**
+ * Alias of [`matchE`](#matchE).
+ *
+ * @category destructors
+ * @since 2.10.0
+ */
+export const fold = matchE
+
+/**
+ * Less strict version of [`matchE`](#matchE).
  *
  * @category destructors
  * @since 2.10.0
  */
-export const matchW: <B, C, A>(
+export const matchEW: <B, C, A>(
   onNone: () => Task<B>,
   onSome: (a: A) => Task<C>
-) => (ma: TaskOption<A>) => Task<B | C> = fold as any
+) => (ma: TaskOption<A>) => Task<B | C> = matchE as any
 
 /**
- * Alias of [`matchW`](#matchW).
+ * Alias of [`matchEW`](#matchEW).
  *
  * @category destructors
  * @since 2.10.0
  */
-export const foldW = matchW
+export const foldW = matchEW
 
 /**
  * @category destructors
diff --git a/src/TaskThese.ts b/src/TaskThese.ts
index 8327d5dd..e4d80a4b 100644
--- a/src/TaskThese.ts
+++ b/src/TaskThese.ts
@@ -129,40 +129,64 @@ export const fromEither: FromEither2<URI>['fromEither'] = T.of
  * @since 2.10.0
  */
 export const match: <E, B, A>(
+  onLeft: (e: E) => B,
+  onRight: (a: A) => B,
+  onBoth: (e: E, a: A) => B
+) => (fa: TaskThese<E, A>) => Task<B> =
+  /*#__PURE__*/
+  TT.match(T.Functor)
+
+/**
+ * Less strict version of [`match`](#match).
+ *
+ * @category destructors
+ * @since 2.10.0
+ */
+export const matchW: <E, B, A, C, D>(
+  onLeft: (e: E) => B,
+  onRight: (a: A) => C,
+  onBoth: (e: E, a: A) => D
+) => (ma: TaskThese<E, A>) => T.Task<B | C | D> = match as any
+
+/**
+ * @category destructors
+ * @since 2.10.0
+ */
+export const matchE: <E, B, A>(
   onLeft: (e: E) => Task<B>,
   onRight: (a: A) => Task<B>,
   onBoth: (e: E, a: A) => Task<B>
 ) => (fa: TaskThese<E, A>) => Task<B> =
   /*#__PURE__*/
-  TT.match(T.Monad)
+  TT.matchE(T.Monad)
 
 /**
- * Alias of [`match`](#match).
+ * Alias of [`matchE`](#matchE).
  *
  * @category destructors
  * @since 2.4.0
  */
-export const fold = match
+export const fold = matchE
 
 /**
- * Less strict version of [`match`](#match).
+ * Less strict version of [`matchE`](#matchE).
  *
  * @category destructors
  * @since 2.10.0
  */
-export const matchW: <E, B, A, C, D>(
+export const matchEW: <E, B, A, C, D>(
   onLeft: (e: E) => Task<B>,
   onRight: (a: A) => Task<C>,
   onBoth: (e: E, a: A) => Task<D>
 ) => (fa: TaskThese<E, A>) => Task<B | C | D> = fold as any
 
 /**
- * Alias of [`matchW`](#matchW).
+ * Alias of [`matchEW`](#matchEW).
  *
  * @category destructors
  * @since 2.10.0
  */
-export const foldW = matchW
+export const foldW = matchEW
 
 // -------------------------------------------------------------------------------------
 // combinators
diff --git a/src/TheseT.ts b/src/TheseT.ts
index b80c23e2..ab24ee9b 100644
--- a/src/TheseT.ts
+++ b/src/TheseT.ts
@@ -1,13 +1,13 @@
 /**
  * @since 2.4.0
  */
-import { ap as ap_, Apply, Apply1, Apply2, Apply2C, Apply3, Apply3C, Apply4 } from './Apply'
-import { Chain, Chain1, Chain2, Chain2C, Chain3, Chain3C, Chain4 } from './Chain'
+import { ap as ap_, Apply, Apply1, Apply2, Apply2C, Apply3, Apply3C } from './Apply'
+import { Chain, Chain1, Chain2, Chain2C, Chain3, Chain3C } from './Chain'
 import { flow, Lazy, pipe } from './function'
-import { Functor, Functor1, Functor2, Functor2C, Functor3, Functor3C, Functor4, map as map_ } from './Functor'
-import { HKT, Kind, Kind2, Kind3, Kind4, URIS, URIS2, URIS3, URIS4 } from './HKT'
-import { Monad, Monad1, Monad2, Monad2C, Monad3, Monad3C, Monad4 } from './Monad'
-import { Pointed, Pointed1, Pointed2, Pointed2C, Pointed3, Pointed3C, Pointed4 } from './Pointed'
+import { Functor, Functor1, Functor2, Functor2C, Functor3, Functor3C, map as map_ } from './Functor'
+import { HKT, Kind, Kind2, Kind3, URIS, URIS2, URIS3 } from './HKT'
+import { Monad, Monad1, Monad2, Monad2C, Monad3, Monad3C } from './Monad'
+import { Pointed, Pointed1, Pointed2, Pointed2C, Pointed3, Pointed3C } from './Pointed'
 import { Semigroup } from './Semigroup'
 import * as T from './These'
 
@@ -16,9 +16,6 @@ import These = T.These
 /**
  * @since 2.10.0
  */
-export function right<F extends URIS4>(
-  F: Pointed4<F>
-): <A, S, R, FE, E = never>(a: A) => Kind4<F, S, R, FE, These<E, A>>
 export function right<F extends URIS3>(F: Pointed3<F>): <A, R, FE, E = never>(a: A) => Kind3<F, R, FE, These<E, A>>
 export function right<F extends URIS3, FE>(F: Pointed3C<F, FE>): <A, R, E = never>(a: A) => Kind3<F, R, FE, These<E, A>>
 export function right<F extends URIS2>(F: Pointed2<F>): <A, FE, E = never>(a: A) => Kind2<F, FE, These<E, A>>
@@ -32,7 +29,6 @@ export function right<F>(F: Pointed<F>): <A, E = never>(a: A) => HKT<F, These<E,
 /**
  * @since 2.10.0
  */
-export function left<F extends URIS4>(F: Pointed4<F>): <E, S, R, FE, A = never>(e: E) => Kind4<F, S, R, FE, These<E, A>>
 export function left<F extends URIS3>(F: Pointed3<F>): <E, R, FE, A = never>(e: E) => Kind3<F, R, FE, These<E, A>>
 export function left<F extends URIS3, FE>(F: Pointed3C<F, FE>): <E, R, A = never>(e: E) => Kind3<F, R, FE, These<E, A>>
 export function left<F extends URIS2>(F: Pointed2<F>): <E, FE, A = never>(e: E) => Kind2<F, FE, These<E, A>>
@@ -46,7 +42,6 @@ export function left<F>(F: Pointed<F>): <E, A = never>(e: E) => HKT<F, These<E,
 /**
  * @since 2.10.0
  */
-export function both<F extends URIS4>(F: Pointed4<F>): <E, A, S, R, FE>(e: E, a: A) => Kind4<F, S, R, FE, These<E, A>>
 export function both<F extends URIS3>(F: Pointed3<F>): <E, A, R, FE>(e: E, a: A) => Kind3<F, R, FE, These<E, A>>
 export function both<F extends URIS3, FE>(F: Pointed3C<F, FE>): <E, A, R>(e: E, a: A) => Kind3<F, R, FE, These<E, A>>
 export function both<F extends URIS2>(F: Pointed2<F>): <E, A, FE>(e: E, a: A) => Kind2<F, FE, These<E, A>>
@@ -60,9 +55,6 @@ export function both<F>(F: Pointed<F>): <E, A = never>(e: E, a: A) => HKT<F, The
 /**
  * @since 2.10.0
  */
-export function rightF<F extends URIS4>(
-  F: Functor4<F>
-): <S, R, FE, A, E = never>(fa: Kind4<F, S, R, FE, A>) => Kind4<F, S, R, FE, These<E, A>>
 export function rightF<F extends URIS3>(
   F: Functor3<F>
 ): <R, FE, A, E = never>(fa: Kind3<F, R, FE, A>) => Kind3<F, R, FE, These<E, A>>
@@ -84,9 +76,6 @@ export function rightF<F>(F: Functor<F>): <A, E = never>(fa: HKT<F, A>) => HKT<F
 /**
  * @since 2.10.0
  */
-export function leftF<F extends URIS4>(
-  F: Functor4<F>
-): <S, R, FE, E, A = never>(fe: Kind4<F, S, R, FE, E>) => Kind4<F, S, R, FE, These<E, A>>
 export function leftF<F extends URIS3>(
   F: Functor3<F>
 ): <R, FE, E, A = never>(fe: Kind3<F, R, FE, E>) => Kind3<F, R, FE, These<E, A>>
@@ -108,9 +97,6 @@ export function leftF<F>(F: Functor<F>): <E, A = never>(fe: HKT<F, E>) => HKT<F,
 /**
  * @since 2.10.0
  */
-export function map<F extends URIS4>(
-  F: Functor4<F>
-): <A, B>(f: (a: A) => B) => <S, R, FE, E>(fa: Kind4<F, S, R, FE, These<E, A>>) => Kind4<F, S, R, FE, These<E, B>>
 export function map<F extends URIS3>(
   F: Functor3<F>
 ): <A, B>(f: (a: A) => B) => <R, FE, E>(fa: Kind3<F, R, FE, These<E, A>>) => Kind3<F, R, FE, These<E, B>>
@@ -134,12 +120,6 @@ export function map<F>(F: Functor<F>): <A, B>(f: (a: A) => B) => <E>(fa: HKT<F,
 /**
  * @since 2.10.0
  */
-export function ap<F extends URIS4, E>(
-  F: Apply4<F>,
-  S: Semigroup<E>
-): <S, R, FE, A>(
-  fa: Kind4<F, S, R, FE, These<E, A>>
-) => <B>(fab: Kind4<F, S, R, FE, These<E, (a: A) => B>>) => Kind4<F, S, R, FE, These<E, B>>
 export function ap<F extends URIS3, E>(
   F: Apply3<F>,
   S: Semigroup<E>
@@ -178,12 +158,6 @@ export function ap<F, E>(
 /**
  * @since 2.10.0
  */
-export function chain<M extends URIS4, E>(
-  M: Monad4<M>,
-  S: Semigroup<E>
-): <A, S, R, ME, B>(
-  f: (a: A) => Kind4<M, S, R, ME, These<E, B>>
-) => (ma: Kind4<M, S, R, ME, These<E, A>>) => Kind4<M, S, R, ME, These<E, B>>
 export function chain<M extends URIS3, E>(
   M: Monad3<M>,
   S: Semigroup<E>
@@ -236,12 +210,6 @@ export function chain<M, E>(
 /**
  * @since 2.10.0
  */
-export function bimap<F extends URIS4>(
-  F: Functor4<F>
-): <E, G, A, B>(
-  f: (e: E) => G,
-  g: (a: A) => B
-) => <S, R, FE>(fea: Kind4<F, S, R, FE, These<E, A>>) => Kind4<F, S, R, FE, These<G, B>>
 export function bimap<F extends URIS3>(
   F: Functor3<F>
 ): <E, G, A, B>(
@@ -275,9 +243,6 @@ export function bimap<F>(
 /**
  * @since 2.10.0
  */
-export function mapLeft<F extends URIS4>(
-  F: Functor4<F>
-): <E, G>(f: (e: E) => G) => <S, R, FE, A>(fea: Kind4<F, S, R, FE, These<E, A>>) => Kind4<F, S, R, FE, These<G, A>>
 export function mapLeft<F extends URIS3>(
   F: Functor3<F>
 ): <E, G>(f: (e: E) => G) => <R, FE, A>(fea: Kind3<F, R, FE, These<E, A>>) => Kind3<F, R, FE, These<G, A>>
@@ -305,56 +270,104 @@ export function mapLeft<F>(
 /**
  * @since 2.10.0
  */
-export function match<M extends URIS4>(
-  M: Chain4<M>
-): <E, S, R, ME, B, A>(
-  onLeft: (e: E) => Kind4<M, S, R, ME, B>,
-  onRight: (a: A) => Kind4<M, S, R, ME, B>,
-  onBoth: (e: E, a: A) => Kind4<M, S, R, ME, B>
-) => (ma: Kind4<M, S, R, ME, These<E, A>>) => Kind4<M, S, R, ME, B>
-export function match<M extends URIS3>(
+export function match<F extends URIS3>(
+  F: Functor3<F>
+): <E, B, A>(
+  onLeft: (e: E) => B,
+  onRight: (a: A) => B,
+  onBoth: (e: E, a: A) => B
+) => <S, R>(ma: Kind3<F, S, R, These<E, A>>) => Kind3<F, S, R, B>
+export function match<F extends URIS3, R>(
+  F: Functor3C<F, R>
+): <E, B, A>(
+  onLeft: (e: E) => B,
+  onRight: (a: A) => B,
+  onBoth: (e: E, a: A) => B
+) => <S>(ma: Kind3<F, S, R, These<E, A>>) => Kind3<F, S, R, B>
+export function match<F extends URIS2>(
+  F: Functor2<F>
+): <E, B, A>(
+  onLeft: (e: E) => B,
+  onRight: (a: A) => B,
+  onBoth: (e: E, a: A) => B
+) => <R>(ma: Kind2<F, R, These<E, A>>) => Kind2<F, R, B>
+export function match<M extends URIS2, R>(
+  F: Functor2C<M, R>
+): <E, B, A>(
+  onLeft: (e: E) => B,
+  onRight: (a: A) => B,
+  onBoth: (e: E, a: A) => B
+) => (ma: Kind2<M, R, These<E, A>>) => Kind2<M, R, B>
+export function match<F extends URIS>(
+  F: Functor1<F>
+): <E, B, A>(
+  onLeft: (e: E) => B,
+  onRight: (a: A) => B,
+  onBoth: (e: E, a: A) => B
+) => (ma: Kind<F, These<E, A>>) => Kind<F, B>
+export function match<F>(
+  F: Functor<F>
+): <E, B, A>(
+  onLeft: (e: E) => B,
+  onRight: (a: A) => B,
+  onBoth: (e: E, a: A) => B
+) => (ma: HKT<F, These<E, A>>) => HKT<F, B>
+export function match<F>(
+  F: Functor<F>
+): <E, B, A>(
+  onLeft: (e: E) => B,
+  onRight: (a: A) => B,
+  onBoth: (e: E, a: A) => B
+) => (ma: HKT<F, These<E, A>>) => HKT<F, B> {
+  return (onLeft, onRight, onBoth) => (ma) => F.map(ma, T.match(onLeft, onRight, onBoth))
+}
+
+/**
+ * @since 2.10.0
+ */
+export function matchE<M extends URIS3>(
   M: Chain3<M>
 ): <E, R, ME, B, A>(
   onLeft: (e: E) => Kind3<M, R, ME, B>,
   onRight: (a: A) => Kind3<M, R, ME, B>,
   onBoth: (e: E, a: A) => Kind3<M, R, ME, B>
 ) => (ma: Kind3<M, R, ME, These<E, A>>) => Kind3<M, R, ME, B>
-export function match<M extends URIS3, ME>(
+export function matchE<M extends URIS3, ME>(
   M: Chain3C<M, ME>
 ): <E, R, B, A>(
   onLeft: (e: E) => Kind3<M, R, ME, B>,
   onRight: (a: A) => Kind3<M, R, ME, B>,
   onBoth: (e: E, a: A) => Kind3<M, R, ME, B>
 ) => (ma: Kind3<M, R, ME, These<E, A>>) => Kind3<M, R, ME, B>
-export function match<M extends URIS2>(
+export function matchE<M extends URIS2>(
   M: Chain2<M>
 ): <E, ME, B, A>(
   onLeft: (e: E) => Kind2<M, ME, B>,
   onRight: (a: A) => Kind2<M, ME, B>,
   onBoth: (e: E, a: A) => Kind2<M, ME, B>
 ) => (ma: Kind2<M, ME, These<E, A>>) => Kind2<M, ME, B>
-export function match<M extends URIS2, ME>(
+export function matchE<M extends URIS2, ME>(
   M: Chain2C<M, ME>
 ): <E, B, A>(
   onLeft: (e: E) => Kind2<M, ME, B>,
   onRight: (a: A) => Kind2<M, ME, B>,
   onBoth: (e: E, a: A) => Kind2<M, ME, B>
 ) => (ma: Kind2<M, ME, These<E, A>>) => Kind2<M, ME, B>
-export function match<M extends URIS>(
+export function matchE<M extends URIS>(
   M: Chain1<M>
 ): <E, B, A>(
   onLeft: (e: E) => Kind<M, B>,
   onRight: (a: A) => Kind<M, B>,
   onBoth: (e: E, a: A) => Kind<M, B>
 ) => (ma: Kind<M, These<E, A>>) => Kind<M, B>
-export function match<M>(
+export function matchE<M>(
   M: Chain<M>
 ): <E, B, A>(
   onLeft: (e: E) => HKT<M, B>,
   onRight: (a: A) => HKT<M, B>,
   onBoth: (e: E, a: A) => HKT<M, B>
 ) => (ma: HKT<M, These<E, A>>) => HKT<M, B>
-export function match<M>(
+export function matchE<M>(
   M: Chain<M>
 ): <E, B, A>(
   onLeft: (e: E) => HKT<M, B>,
@@ -367,9 +380,6 @@ export function match<M>(
 /**
  * @since 2.10.0
  */
-export function swap<F extends URIS4>(
-  F: Functor4<F>
-): <S, R, FE, E, A>(ma: Kind4<F, S, R, FE, These<E, A>>) => Kind4<F, S, R, FE, These<A, E>>
 export function swap<F extends URIS3>(
   F: Functor3<F>
 ): <R, FE, E, A>(ma: Kind3<F, R, FE, These<E, A>>) => Kind3<F, R, FE, These<A, E>>
@@ -391,12 +401,6 @@ export function swap<F>(F: Functor<F>): <E, A>(ma: HKT<F, These<E, A>>) => HKT<F
 /**
  * @since 2.10.0
  */
-export function toTuple2<F extends URIS4>(
-  F: Functor4<F>
-): <E, A>(
-  e: Lazy<E>,
-  a: Lazy<A>
-) => <S, R, FE>(fa: Kind4<F, S, R, FE, These<E, A>>) => Kind4<F, S, R, FE, readonly [E, A]>
 export function toTuple2<F extends URIS3>(
   F: Functor3<F>
 ): <E, A>(e: Lazy<E>, a: Lazy<A>) => <R, FE>(fa: Kind3<F, R, FE, These<E, A>>) => Kind3<F, R, FE, readonly [E, A]>
@@ -559,7 +563,7 @@ export function getTheseM<M>(M: Monad<M>): TheseM<M> {
   const _map = map(M)
   const _bimap = bimap(M)
   const _mapLeft = mapLeft(M)
-  const _fold = match(M)
+  const _fold = matchE(M)
   const _toTuple2: <E, A>(e: Lazy<E>, a: Lazy<A>) => (fa: HKT<M, T.These<E, A>>) => HKT<M, [E, A]> = toTuple2(M) as any
   const of = right(M)
 
diff --git a/src/internal.ts b/src/internal.ts
index 07a0cdf2..c923ad7a 100644
--- a/src/internal.ts
+++ b/src/internal.ts
@@ -2,7 +2,9 @@
  * @since 2.10.0
  */
 import { Either, Left } from './Either'
+import { NonEmptyArray } from './NonEmptyArray'
 import { Option, Some } from './Option'
+import { ReadonlyNonEmptyArray } from './ReadonlyNonEmptyArray'
 
 // -------------------------------------------------------------------------------------
 // Option
@@ -24,3 +26,10 @@ export const isLeft = <E, A>(ma: Either<E, A>): ma is Left<E> => ma._tag === 'Le
 
 /** @internal */
 export const hasOwnProperty = Object.prototype.hasOwnProperty
+
+// -------------------------------------------------------------------------------------
+// NonEmptyArray
+// -------------------------------------------------------------------------------------
+
+/** @internal */
+export const fromReadonlyNonEmptyArray = <A>(as: ReadonlyNonEmptyArray<A>): NonEmptyArray<A> => [as[0], ...as.slice(1)]


Test patch:
diff --git a/test/Date.ts b/test/Date.ts
index 808b7f1b..9896108b 100644
--- a/test/Date.ts
+++ b/test/Date.ts
@@ -39,9 +39,7 @@ describe('Date', () => {
 
   it('create', () => {
     const d1 = _.create()
-    const m2 = new Date().getTime()
     U.deepStrictEqual(d1 instanceof Date, true)
-    U.deepStrictEqual(d1.getTime(), m2)
   })
 
   it('now', () => {
diff --git a/test/IOEither.ts b/test/IOEither.ts
index 38dcb7b1..2ab221ad 100644
--- a/test/IOEither.ts
+++ b/test/IOEither.ts
@@ -512,4 +512,26 @@ describe('IOEither', () => {
     U.deepStrictEqual(_.toUnion(_.right(1))(), 1)
     U.deepStrictEqual(_.toUnion(_.left('a'))(), 'a')
   })
+
+  // -------------------------------------------------------------------------------------
+  // destructors
+  // -------------------------------------------------------------------------------------
+
+  it('match', () => {
+    const f = _.match(
+      () => 'left',
+      () => 'right'
+    )
+    U.deepStrictEqual(f(_.right(1))(), 'right')
+    U.deepStrictEqual(f(_.left(1))(), 'left')
+  })
+
+  it('matchE', () => {
+    const f = _.matchE(
+      () => I.of('left'),
+      () => I.of('right')
+    )
+    U.deepStrictEqual(f(_.right(1))(), 'right')
+    U.deepStrictEqual(f(_.left(1))(), 'left')
+  })
 })
diff --git a/test/ReaderEither.ts b/test/ReaderEither.ts
index f5ffc3b3..0cd1b8fa 100644
--- a/test/ReaderEither.ts
+++ b/test/ReaderEither.ts
@@ -254,4 +254,22 @@ describe('ReaderEither', () => {
     U.deepStrictEqual(left(s2)({}), E.left(''))
     U.deepStrictEqual(right(s2)({}), E.right(1))
   })
+
+  it('match', () => {
+    const f = _.match(
+      () => 'left',
+      () => 'right'
+    )
+    U.deepStrictEqual(f(_.right(1))({}), 'right')
+    U.deepStrictEqual(f(_.left('a'))({}), 'left')
+  })
+
+  it('matchE', () => {
+    const f = _.matchE(
+      () => R.of('left'),
+      () => R.of('right')
+    )
+    U.deepStrictEqual(f(_.right(1))({}), 'right')
+    U.deepStrictEqual(f(_.left('a'))({}), 'left')
+  })
 })
diff --git a/test/ReaderTaskEither.ts b/test/ReaderTaskEither.ts
index bedbe6b4..1267bf98 100644
--- a/test/ReaderTaskEither.ts
+++ b/test/ReaderTaskEither.ts
@@ -453,4 +453,22 @@ describe('ReaderTaskEither', () => {
     U.deepStrictEqual(await left(s2)({})(), E.left(''))
     U.deepStrictEqual(await right(s2)({})(), E.right(1))
   })
+
+  it('match', async () => {
+    const f = _.match(
+      () => 'left',
+      () => 'right'
+    )
+    U.deepStrictEqual(await f(_.right(1))({})(), 'right')
+    U.deepStrictEqual(await f(_.left(''))({})(), 'left')
+  })
+
+  it('matchE', async () => {
+    const f = _.matchE(
+      () => RT.of('left'),
+      () => RT.of('right')
+    )
+    U.deepStrictEqual(await f(_.right(1))({})(), 'right')
+    U.deepStrictEqual(await f(_.left(''))({})(), 'left')
+  })
 })
diff --git a/test/TaskEither.ts b/test/TaskEither.ts
index 316eeb4d..e8d73648 100644
--- a/test/TaskEither.ts
+++ b/test/TaskEither.ts
@@ -538,4 +538,22 @@ describe('TaskEither', () => {
     U.deepStrictEqual(await pipe([left('b'), right(4)], _.sequenceSeqArray)(), E.left('b'))
     U.deepStrictEqual(log, [1, 2, 3, 'a', 'b'])
   })
+
+  it('match', async () => {
+    const f = _.match(
+      () => 'left',
+      () => 'right'
+    )
+    U.deepStrictEqual(await f(_.right(1))(), 'right')
+    U.deepStrictEqual(await f(_.left(''))(), 'left')
+  })
+
+  it('matchE', async () => {
+    const f = _.matchE(
+      () => T.of('left'),
+      () => T.of('right')
+    )
+    U.deepStrictEqual(await f(_.right(1))(), 'right')
+    U.deepStrictEqual(await f(_.left(''))(), 'left')
+  })
 })
diff --git a/test/TaskOption.ts b/test/TaskOption.ts
index 43ef5201..72573ff4 100644
--- a/test/TaskOption.ts
+++ b/test/TaskOption.ts
@@ -215,4 +215,22 @@ describe('TaskOption', () => {
     U.deepStrictEqual(await g(1)(), O.some(1))
     U.deepStrictEqual(await g(-1)(), O.none)
   })
+
+  it('match', async () => {
+    const f = _.match(
+      () => 'none',
+      (a) => `some(${a})`
+    )
+    U.deepStrictEqual(await pipe(_.some(1), f)(), 'some(1)')
+    U.deepStrictEqual(await pipe(_.none, f)(), 'none')
+  })
+
+  it('matchE', async () => {
+    const f = _.matchE(
+      () => T.of('none'),
+      (a) => T.of(`some(${a})`)
+    )
+    U.deepStrictEqual(await pipe(_.some(1), f)(), 'some(1)')
+    U.deepStrictEqual(await pipe(_.none, f)(), 'none')
+  })
 })
diff --git a/test/TaskThese.ts b/test/TaskThese.ts
index 581923d5..3a89c545 100644
--- a/test/TaskThese.ts
+++ b/test/TaskThese.ts
@@ -150,4 +150,26 @@ describe('TaskThese', () => {
     U.deepStrictEqual(await f(_.left('a'))(), ['a', 2])
     U.deepStrictEqual(await f(_.both('a', 1))(), ['a', 1])
   })
+
+  it('match', async () => {
+    const match = _.match(
+      (e) => `left ${e}`,
+      (a) => `right ${a}`,
+      (e, a) => `both ${e} ${a}`
+    )
+    U.deepStrictEqual(await pipe(_.right(1), match)(), 'right 1')
+    U.deepStrictEqual(await pipe(_.left('a'), match)(), 'left a')
+    U.deepStrictEqual(await pipe(_.both('a', 1), match)(), 'both a 1')
+  })
+
+  it('matchE', async () => {
+    const matchE = _.matchE(
+      (e) => T.of(`left ${e}`),
+      (a) => T.of(`right ${a}`),
+      (e, a) => T.of(`both ${e} ${a}`)
+    )
+    U.deepStrictEqual(await pipe(_.right(1), matchE)(), 'right 1')
+    U.deepStrictEqual(await pipe(_.left('a'), matchE)(), 'left a')
+    U.deepStrictEqual(await pipe(_.both('a', 1), matchE)(), 'both a 1')
+  })
 })