Repository: gcanti/fp-ts
Pull request #873 (2019-05-17 08:58:25)

make some APIs "data last"


Patch:
diff --git a/docs/modules/Either.ts.md b/docs/modules/Either.ts.md
index dac92da2..0d4ced57 100644
--- a/docs/modules/Either.ts.md
+++ b/docs/modules/Either.ts.md
@@ -43,6 +43,7 @@ either.map(left(23), double) // left(23)
 - [URI (type alias)](#uri-type-alias)
 - [URI (constant)](#uri-constant)
 - [either (constant)](#either-constant)
+- [elem (function)](#elem-function)
 - [filterOrElse (function)](#filterorelse-function)
 - [fold (function)](#fold-function)
 - [fromNullable (function)](#fromnullable-function)
@@ -142,17 +143,26 @@ export const either: Monad2<URI> &
 
 Added in v2.0.0
 
+# elem (function)
+
+**Signature**
+
+```ts
+export function elem<A>(E: Eq<A>): <L>(a: A, ma: Either<L, A>) => boolean { ... }
+```
+
+Added in v2.0.0
+
 # filterOrElse (function)
 
 **Signature**
 
 ```ts
 export function filterOrElse<L, A, B extends A>(
-  ma: Either<L, A>,
   refinement: Refinement<A, B>,
   zero: (a: A) => L
-): Either<L, B>
-export function filterOrElse<L, A>(ma: Either<L, A>, predicate: Predicate<A>, zero: (a: A) => L): Either<L, A> { ... }
+): (ma: Either<L, A>) => Either<L, B>
+export function filterOrElse<L, A>(predicate: Predicate<A>, zero: (a: A) => L): (ma: Either<L, A>) => Either<L, A> { ... }
 ```
 
 Added in v2.0.0
@@ -162,7 +172,7 @@ Added in v2.0.0
 **Signature**
 
 ```ts
-export function fold<L, A, R>(ma: Either<L, A>, onLeft: (l: L) => R, onRight: (a: A) => R): R { ... }
+export function fold<L, A, R>(onLeft: (l: L) => R, onRight: (a: A) => R): (ma: Either<L, A>) => R { ... }
 ```
 
 Added in v2.0.0
@@ -278,7 +288,7 @@ Added in v2.0.0
 **Signature**
 
 ```ts
-export function getOrElse<L, A>(ma: Either<L, A>, f: (l: L) => A): A { ... }
+export function getOrElse<L, A>(f: (l: L) => A): (ma: Either<L, A>) => A { ... }
 ```
 
 Added in v2.0.0
@@ -373,7 +383,7 @@ Added in v2.0.0
 **Signature**
 
 ```ts
-export function orElse<L, A, M>(ma: Either<L, A>, f: (l: L) => Either<M, A>): Either<M, A> { ... }
+export function orElse<L, A, M>(f: (l: L) => Either<M, A>): (ma: Either<L, A>) => Either<M, A> { ... }
 ```
 
 Added in v2.0.0
diff --git a/docs/modules/EitherT.ts.md b/docs/modules/EitherT.ts.md
index a8f79a47..d9516a1c 100644
--- a/docs/modules/EitherT.ts.md
+++ b/docs/modules/EitherT.ts.md
@@ -25,11 +25,15 @@ parent: Modules
 ```ts
 export interface EitherM<M> extends ApplicativeComposition02<M, URI> {
   readonly chain: <L, A, B>(ma: EitherT<M, L, A>, f: (a: A) => EitherT<M, L, B>) => EitherT<M, L, B>
-  readonly fold: <L, A, R>(ma: EitherT<M, L, A>, onLeft: (l: L) => HKT<M, R>, onRight: (a: A) => HKT<M, R>) => HKT<M, R>
+  readonly alt: <L, A>(fx: EitherT<M, L, A>, f: () => EitherT<M, L, A>) => EitherT<M, L, A>
+  readonly fold: <L, A, R>(
+    onLeft: (l: L) => HKT<M, R>,
+    onRight: (a: A) => HKT<M, R>
+  ) => (ma: EitherT<M, L, A>) => HKT<M, R>
   readonly bimap: <L, A, N, B>(ma: EitherT<M, L, A>, f: (l: L) => N, g: (a: A) => B) => EitherT<M, N, B>
   readonly mapLeft: <L, A, N>(ma: EitherT<M, L, A>, f: (l: L) => N) => EitherT<M, N, A>
-  readonly getOrElse: <L, A>(ma: EitherT<M, L, A>, f: (l: L) => HKT<M, A>) => HKT<M, A>
-  readonly orElse: <L, A, N>(ma: EitherT<M, L, A>, f: (l: L) => EitherT<M, N, A>) => EitherT<M, N, A>
+  readonly getOrElse: <L, A>(f: (l: L) => HKT<M, A>) => (ma: EitherT<M, L, A>) => HKT<M, A>
+  readonly orElse: <L, A, N>(f: (l: L) => EitherT<M, N, A>) => (ma: EitherT<M, L, A>) => EitherT<M, N, A>
   readonly swap: <L, A>(ma: EitherT<M, L, A>) => EitherT<M, A, L>
   readonly rightM: <L, A>(ma: HKT<M, A>) => EitherT<M, L, A>
   readonly leftM: <L, A>(ml: HKT<M, L>) => EitherT<M, L, A>
@@ -51,15 +55,15 @@ Added in v2.0.0
 ```ts
 export interface EitherM1<M extends URIS> extends ApplicativeComposition12<M, URI> {
   readonly chain: <L, A, B>(ma: EitherT1<M, L, A>, f: (a: A) => EitherT1<M, L, B>) => EitherT1<M, L, B>
+  readonly alt: <L, A>(fx: EitherT1<M, L, A>, f: () => EitherT1<M, L, A>) => EitherT1<M, L, A>
   readonly fold: <L, A, R>(
-    ma: EitherT1<M, L, A>,
     onLeft: (l: L) => Type<M, R>,
     onRight: (a: A) => Type<M, R>
-  ) => Type<M, R>
+  ) => (ma: EitherT1<M, L, A>) => Type<M, R>
   readonly bimap: <L, A, N, B>(ma: EitherT1<M, L, A>, f: (l: L) => N, g: (a: A) => B) => EitherT1<M, N, B>
   readonly mapLeft: <L, A, N>(ma: EitherT1<M, L, A>, f: (l: L) => N) => EitherT1<M, N, A>
-  readonly getOrElse: <L, A>(ma: EitherT1<M, L, A>, f: (l: L) => Type<M, A>) => Type<M, A>
-  readonly orElse: <L, A, N>(ma: EitherT1<M, L, A>, f: (l: L) => EitherT1<M, N, A>) => EitherT1<M, N, A>
+  readonly getOrElse: <L, A>(f: (l: L) => Type<M, A>) => (ma: EitherT1<M, L, A>) => Type<M, A>
+  readonly orElse: <L, A, N>(f: (l: L) => EitherT1<M, N, A>) => (ma: EitherT1<M, L, A>) => EitherT1<M, N, A>
   readonly swap: <L, A>(ma: EitherT1<M, L, A>) => EitherT1<M, A, L>
   readonly rightM: <L, A>(ma: Type<M, A>) => EitherT1<M, L, A>
   readonly leftM: <L, A>(ml: Type<M, L>) => EitherT1<M, L, A>
@@ -81,15 +85,17 @@ Added in v2.0.0
 ```ts
 export interface EitherM2<M extends URIS2> extends ApplicativeComposition22<M, URI> {
   readonly chain: <LM, L, A, B>(ma: EitherT2<M, LM, L, A>, f: (a: A) => EitherT2<M, LM, L, B>) => EitherT2<M, LM, L, B>
+  readonly alt: <LM, L, A>(fx: EitherT2<M, LM, L, A>, f: () => EitherT2<M, LM, L, A>) => EitherT2<M, LM, L, A>
   readonly fold: <LM, L, A, R>(
-    ma: EitherT2<M, LM, L, A>,
     onLeft: (l: L) => Type2<M, LM, R>,
     onRight: (a: A) => Type2<M, LM, R>
-  ) => Type2<M, LM, R>
+  ) => (ma: EitherT2<M, LM, L, A>) => Type2<M, LM, R>
   readonly bimap: <LM, L, A, N, B>(ma: EitherT2<M, LM, L, A>, f: (l: L) => N, g: (a: A) => B) => EitherT2<M, LM, N, B>
   readonly mapLeft: <LM, L, A, N>(ma: EitherT2<M, LM, L, A>, f: (l: L) => N) => EitherT2<M, LM, N, A>
-  readonly getOrElse: <LM, L, A>(ma: EitherT2<M, LM, L, A>, f: (l: L) => Type2<M, LM, A>) => Type2<M, LM, A>
-  readonly orElse: <LM, L, A, N>(ma: EitherT2<M, LM, L, A>, f: (l: L) => EitherT2<M, LM, N, A>) => EitherT2<M, LM, N, A>
+  readonly getOrElse: <LM, L, A>(f: (l: L) => Type2<M, LM, A>) => (ma: EitherT2<M, LM, L, A>) => Type2<M, LM, A>
+  readonly orElse: <LM, L, A, N>(
+    f: (l: L) => EitherT2<M, LM, N, A>
+  ) => (ma: EitherT2<M, LM, L, A>) => EitherT2<M, LM, N, A>
   readonly swap: <LM, L, A>(ma: EitherT2<M, LM, L, A>) => EitherT2<M, LM, A, L>
   readonly rightM: <LM, L, A>(ma: Type2<M, LM, A>) => EitherT2<M, LM, L, A>
   readonly leftM: <LM, L, A>(ml: Type2<M, LM, L>) => EitherT2<M, LM, L, A>
diff --git a/docs/modules/IOEither.ts.md b/docs/modules/IOEither.ts.md
index 468d7ad7..814592dc 100644
--- a/docs/modules/IOEither.ts.md
+++ b/docs/modules/IOEither.ts.md
@@ -90,7 +90,7 @@ Added in v2.0.0
 **Signature**
 
 ```ts
-export const fold: <L, A, R>(ma: IOEither<L, A>, onLeft: (l: L) => IO<R>, onRight: (a: A) => IO<R>) => IO<R> = ...
+export const  = ...
 ```
 
 Added in v2.0.0
@@ -110,7 +110,7 @@ Added in v2.0.0
 **Signature**
 
 ```ts
-export const getOrElse: <L, A>(ma: IOEither<L, A>, f: (l: L) => IO<A>) => IO<A> = ...
+export const getOrElse: <L, A>(f: (l: L) => IO<A>) => (ma: IOEither<L, A>) => IO<A> = ...
 ```
 
 Added in v2.0.0
@@ -150,7 +150,7 @@ Added in v2.0.0
 **Signature**
 
 ```ts
-export const orElse: <L, A, M>(ma: IOEither<L, A>, f: (l: L) => IOEither<M, A>) => IOEither<M, A> = ...
+export const orElse: <L, A, M>(f: (l: L) => IOEither<M, A>) => (ma: IOEither<L, A>) => IOEither<M, A> = ...
 ```
 
 Added in v2.0.0
@@ -191,11 +191,10 @@ Added in v2.0.0
 
 ```ts
 export function filterOrElse<L, A, B extends A>(
-  ma: IOEither<L, A>,
   p: Refinement<A, B>,
   zero: (a: A) => L
-): IOEither<L, B>
-export function filterOrElse<L, A>(ma: IOEither<L, A>, p: Predicate<A>, zero: (a: A) => L): IOEither<L, A> { ... }
+): (ma: IOEither<L, A>) => IOEither<L, B>
+export function filterOrElse<L, A>(p: Predicate<A>, zero: (a: A) => L): (ma: IOEither<L, A>) => IOEither<L, A> { ... }
 ```
 
 Added in v2.0.0
diff --git a/docs/modules/Option.ts.md b/docs/modules/Option.ts.md
index 1913b033..c45f6d49 100644
--- a/docs/modules/Option.ts.md
+++ b/docs/modules/Option.ts.md
@@ -48,8 +48,8 @@ import { getOrElse } from 'fp-ts/lib/Option'
 
 const value1 = head(['foo', 'bar']) // some('foo)
 const value2 = head([]) // none
-getOrElse(value1, 'No value') // 'foo'
-getOrElse(value2, 'No value') // 'No value'
+getOrElse(() => 'No value')(value1) // 'foo'
+getOrElse(() => 'No value')(value2) // 'No value'
 ```
 
 Checking whether option has value:
@@ -68,8 +68,8 @@ import { fold } from 'fp-ts/lib/Option'
 
 const x: Option<number> = some(3)
 const y: Option<number> = none
-fold(x, 1, n => n * 3) // 9
-fold(y, 1, n => n * 3) // 1
+fold(1, n => n * 3)(x) // 9
+fold(1, n => n * 3)(y) // 1
 ```
 
 You can chain several possibly failing computations using the `chain` function
@@ -223,7 +223,7 @@ Added in v2.0.0
 **Signature**
 
 ```ts
-export function exists<A>(ma: Option<A>, predicate: Predicate<A>): boolean { ... }
+export function exists<A>(predicate: Predicate<A>): (ma: Option<A>) => boolean { ... }
 ```
 
 Added in v2.0.0
@@ -233,7 +233,7 @@ Added in v2.0.0
 **Signature**
 
 ```ts
-export function fold<A, R>(ma: Option<A>, onNone: () => R, onSome: (a: A) => R): R { ... }
+export function fold<A, R>(onNone: () => R, onSome: (a: A) => R): (ma: Option<A>) => R { ... }
 ```
 
 Added in v2.0.0
@@ -471,7 +471,7 @@ Added in v2.0.0
 **Signature**
 
 ```ts
-export function getOrElse<A>(ma: Option<A>, f: () => A): A { ... }
+export function getOrElse<A>(f: () => A): (ma: Option<A>) => A { ... }
 ```
 
 Added in v2.0.0
@@ -581,7 +581,7 @@ Added in v2.0.0
 **Signature**
 
 ```ts
-export function mapNullable<A, B>(ma: Option<A>, f: (a: A) => B | null | undefined): Option<B> { ... }
+export function mapNullable<A, B>(f: (a: A) => B | null | undefined): (ma: Option<A>) => Option<B> { ... }
 ```
 
 Added in v2.0.0
diff --git a/docs/modules/OptionT.ts.md b/docs/modules/OptionT.ts.md
index 0b197d5d..d98ac35e 100644
--- a/docs/modules/OptionT.ts.md
+++ b/docs/modules/OptionT.ts.md
@@ -11,7 +11,6 @@ parent: Modules
 - [OptionM (interface)](#optionm-interface)
 - [OptionM1 (interface)](#optionm1-interface)
 - [OptionM2 (interface)](#optionm2-interface)
-- [OptionM2C (interface)](#optionm2c-interface)
 - [OptionT (interface)](#optiont-interface)
 - [OptionT1 (type alias)](#optiont1-type-alias)
 - [OptionT2 (type alias)](#optiont2-type-alias)
@@ -26,8 +25,9 @@ parent: Modules
 ```ts
 export interface OptionM<M> extends ApplicativeComposition01<M, URI> {
   readonly chain: <A, B>(ma: OptionT<M, A>, f: (a: A) => OptionT<M, B>) => OptionT<M, B>
-  readonly fold: <A, R>(ma: OptionT<M, A>, onNone: () => HKT<M, R>, onSome: (a: A) => HKT<M, R>) => HKT<M, R>
-  readonly getOrElse: <A>(ma: OptionT<M, A>, onNone: () => HKT<M, A>) => HKT<M, A>
+  readonly alt: <A>(fx: OptionT<M, A>, fy: () => OptionT<M, A>) => OptionT<M, A>
+  readonly fold: <A, R>(onNone: () => HKT<M, R>, onSome: (a: A) => HKT<M, R>) => (ma: OptionT<M, A>) => HKT<M, R>
+  readonly getOrElse: <A>(onNone: () => HKT<M, A>) => (ma: OptionT<M, A>) => HKT<M, A>
   readonly fromM: <A>(ma: HKT<M, A>) => OptionT<M, A>
   readonly fromOption: <A>(ma: Option<A>) => OptionT<M, A>
   readonly none: () => OptionT<M, never>
@@ -43,8 +43,9 @@ Added in v2.0.0
 ```ts
 export interface OptionM1<M extends URIS> extends ApplicativeComposition11<M, URI> {
   readonly chain: <A, B>(ma: OptionT1<M, A>, f: (a: A) => OptionT1<M, B>) => OptionT1<M, B>
-  readonly fold: <A, R>(ma: OptionT1<M, A>, onNone: () => Type<M, R>, onSome: (a: A) => Type<M, R>) => Type<M, R>
-  readonly getOrElse: <A>(ma: OptionT1<M, A>, onNone: () => Type<M, A>) => Type<M, A>
+  readonly alt: <A>(fx: OptionT1<M, A>, fy: () => OptionT1<M, A>) => OptionT1<M, A>
+  readonly fold: <A, R>(onNone: () => Type<M, R>, onSome: (a: A) => Type<M, R>) => (ma: OptionT1<M, A>) => Type<M, R>
+  readonly getOrElse: <A>(onNone: () => Type<M, A>) => (ma: OptionT1<M, A>) => Type<M, A>
   readonly fromM: <A>(ma: Type<M, A>) => OptionT1<M, A>
   readonly fromOption: <A>(ma: Option<A>) => OptionT1<M, A>
   readonly none: () => OptionT1<M, never>
@@ -60,12 +61,12 @@ Added in v2.0.0
 ```ts
 export interface OptionM2<M extends URIS2> extends ApplicativeComposition21<M, URI> {
   readonly chain: <L, A, B>(ma: OptionT2<M, L, A>, f: (a: A) => OptionT2<M, L, B>) => OptionT2<M, L, B>
+  readonly alt: <L, A>(fx: OptionT2<M, L, A>, fy: () => OptionT2<M, L, A>) => OptionT2<M, L, A>
   readonly fold: <L, A, R>(
-    ma: OptionT2<M, L, A>,
     onNone: () => Type2<M, L, R>,
     onSome: (a: A) => Type2<M, L, R>
-  ) => Type2<M, L, R>
-  readonly getOrElse: <L, A>(ma: OptionT2<M, L, A>, onNone: () => Type2<M, L, A>) => Type2<M, L, A>
+  ) => (ma: OptionT2<M, L, A>) => Type2<M, L, R>
+  readonly getOrElse: <L, A>(onNone: () => Type2<M, L, A>) => (ma: OptionT2<M, L, A>) => Type2<M, L, A>
   readonly fromM: <L, A>(ma: Type2<M, L, A>) => OptionT2<M, L, A>
   readonly fromOption: <L, A>(ma: Option<A>) => OptionT2<M, L, A>
   readonly none: <L>() => OptionT2<M, L, never>
@@ -74,27 +75,6 @@ export interface OptionM2<M extends URIS2> extends ApplicativeComposition21<M, U
 
 Added in v2.0.0
 
-# OptionM2C (interface)
-
-**Signature**
-
-```ts
-export interface OptionM2C<M extends URIS2, L> extends ApplicativeComposition2C1<M, URI, L> {
-  readonly chain: <A, B>(ma: OptionT2<M, L, A>, f: (a: A) => OptionT2<M, L, B>) => OptionT2<M, L, B>
-  readonly fold: <A, R>(
-    ma: OptionT2<M, L, A>,
-    onNone: () => Type2<M, L, R>,
-    onSome: (a: A) => Type2<M, L, R>
-  ) => Type2<M, L, R>
-  readonly getOrElse: <A>(ma: OptionT2<M, L, A>, onNone: () => Type2<M, L, A>) => Type2<M, L, A>
-  readonly fromM: <A>(ma: Type2<M, L, A>) => OptionT2<M, L, A>
-  readonly fromOption: <A>(ma: Option<A>) => OptionT2<M, L, A>
-  readonly none: () => OptionT2<M, L, never>
-}
-```
-
-Added in v2.0.0
-
 # OptionT (interface)
 
 **Signature**
@@ -131,7 +111,6 @@ Added in v2.0.0
 
 ```ts
 export function getOptionM<M extends URIS2>(M: Monad2<M>): OptionM2<M>
-export function getOptionM<M extends URIS2, L>(M: Monad2C<M, L>): OptionM2C<M, L>
 export function getOptionM<M extends URIS>(M: Monad1<M>): OptionM1<M>
 export function getOptionM<M>(M: Monad<M>): OptionM<M> { ... }
 ```
diff --git a/docs/modules/Reader.ts.md b/docs/modules/Reader.ts.md
index 0b33d8b7..0cc7be51 100644
--- a/docs/modules/Reader.ts.md
+++ b/docs/modules/Reader.ts.md
@@ -83,7 +83,7 @@ changes the value of the local context during the execution of the action `ma`
 **Signature**
 
 ```ts
-export const local: <E, A, D>(ma: Reader<E, A>, f: (d: D) => E) => Reader<D, A> = ...
+export const local: <D, E>(f: (d: D) => E) => <A>(ma: Reader<E, A>) => Reader<D, A> = ...
 ```
 
 Added in v2.0.0
diff --git a/docs/modules/ReaderT.ts.md b/docs/modules/ReaderT.ts.md
index fad0856c..7371b67a 100644
--- a/docs/modules/ReaderT.ts.md
+++ b/docs/modules/ReaderT.ts.md
@@ -32,7 +32,7 @@ export interface ReaderM<M> {
   readonly chain: <E, A, B>(ma: ReaderT<M, E, A>, f: (a: A) => ReaderT<M, E, B>) => ReaderT<M, E, B>
   readonly ask: <E>() => ReaderT<M, E, E>
   readonly asks: <E, A>(f: (e: E) => A) => ReaderT<M, E, A>
-  readonly local: <E, A, D>(ma: ReaderT<M, E, A>, f: (d: D) => E) => ReaderT<M, D, A>
+  readonly local: <D, E>(f: (d: D) => E) => <A>(ma: ReaderT<M, E, A>) => ReaderT<M, D, A>
   readonly fromReader: <E, A>(ma: Reader<E, A>) => ReaderT<M, E, A>
   readonly fromM: <E, A>(ma: HKT<M, A>) => ReaderT<M, E, A>
 }
@@ -52,7 +52,7 @@ export interface ReaderM1<M extends URIS> {
   readonly chain: <E, A, B>(ma: ReaderT1<M, E, A>, f: (a: A) => ReaderT1<M, E, B>) => ReaderT1<M, E, B>
   readonly ask: <E>() => ReaderT1<M, E, E>
   readonly asks: <E, A>(f: (e: E) => A) => ReaderT1<M, E, A>
-  readonly local: <E, A, D>(ma: ReaderT1<M, E, A>, f: (d: D) => E) => ReaderT1<M, D, A>
+  readonly local: <D, E>(f: (d: D) => E) => <A>(ma: ReaderT1<M, E, A>) => ReaderT1<M, D, A>
   readonly fromReader: <E, A>(ma: Reader<E, A>) => ReaderT1<M, E, A>
   readonly fromM: <E, A>(ma: Type<M, A>) => ReaderT1<M, E, A>
 }
@@ -72,7 +72,7 @@ export interface ReaderM2<M extends URIS2> {
   readonly chain: <E, L, A, B>(ma: ReaderT2<M, E, L, A>, f: (a: A) => ReaderT2<M, E, L, B>) => ReaderT2<M, E, L, B>
   readonly ask: <E, L>() => ReaderT2<M, E, L, E>
   readonly asks: <E, L, A>(f: (e: E) => A) => ReaderT2<M, E, L, A>
-  readonly local: <E, L, A, D>(ma: ReaderT2<M, E, L, A>, f: (d: D) => E) => ReaderT2<M, D, L, A>
+  readonly local: <D, E>(f: (d: D) => E) => <L, A>(ma: ReaderT2<M, E, L, A>) => ReaderT2<M, D, L, A>
   readonly fromReader: <E, L, A>(ma: Reader<E, A>) => ReaderT2<M, E, L, A>
   readonly fromM: <E, L, A>(ma: Type2<M, L, A>) => ReaderT2<M, E, L, A>
 }
@@ -98,7 +98,7 @@ export interface ReaderM3<M extends URIS3> {
   ) => ReaderT3<M, E, U, L, B>
   readonly ask: <E, U, L>() => ReaderT3<M, E, U, L, E>
   readonly asks: <E, U, L, A>(f: (e: E) => A) => ReaderT3<M, E, U, L, A>
-  readonly local: <E, U, L, A, D>(ma: ReaderT3<M, E, U, L, A>, f: (d: D) => E) => ReaderT3<M, D, U, L, A>
+  readonly local: <D, E>(f: (d: D) => E) => <U, L, A>(ma: ReaderT3<M, E, U, L, A>) => ReaderT3<M, D, U, L, A>
   readonly fromReader: <E, U, L, A>(ma: Reader<E, A>) => ReaderT3<M, E, U, L, A>
   readonly fromM: <E, U, L, A>(ma: Type3<M, U, L, A>) => ReaderT3<M, E, U, L, A>
 }
diff --git a/docs/modules/ReaderTaskEither.ts.md b/docs/modules/ReaderTaskEither.ts.md
index 55ae38a1..76db564e 100644
--- a/docs/modules/ReaderTaskEither.ts.md
+++ b/docs/modules/ReaderTaskEither.ts.md
@@ -103,7 +103,7 @@ Added in v2.0.0
 **Signature**
 
 ```ts
-export const local: <E, L, A, D>(ma: ReaderTaskEither<E, L, A>, f: (f: D) => E) => ReaderTaskEither<D, L, A> = ...
+export const  = ...
 ```
 
 Added in v2.0.0
@@ -156,10 +156,9 @@ Added in v2.0.0
 
 ```ts
 export function fold<E, L, A, R>(
-  ma: ReaderTaskEither<E, L, A>,
   onLeft: (l: L) => Reader<E, Task<R>>,
   onRight: (a: A) => Reader<E, Task<R>>
-): Reader<E, Task<R>> { ... }
+): (ma: ReaderTaskEither<E, L, A>) => Reader<E, Task<R>> { ... }
 ```
 
 Added in v2.0.0
@@ -217,9 +216,8 @@ Added in v2.0.0
 
 ```ts
 export function getOrElse<E, L, A>(
-  ma: ReaderTaskEither<E, L, A>,
   onLeft: (l: L) => Reader<E, Task<A>>
-): Reader<E, Task<A>> { ... }
+): (ma: ReaderTaskEither<E, L, A>) => Reader<E, Task<A>> { ... }
 ```
 
 Added in v2.0.0
@@ -270,9 +268,8 @@ Added in v2.0.0
 
 ```ts
 export function orElse<E, L, A, M>(
-  ma: ReaderTaskEither<E, L, A>,
   f: (l: L) => ReaderTaskEither<E, M, A>
-): ReaderTaskEither<E, M, A> { ... }
+): (ma: ReaderTaskEither<E, L, A>) => ReaderTaskEither<E, M, A> { ... }
 ```
 
 Added in v2.0.0
diff --git a/docs/modules/Store.ts.md b/docs/modules/Store.ts.md
index 2f677284..a30c36aa 100644
--- a/docs/modules/Store.ts.md
+++ b/docs/modules/Store.ts.md
@@ -71,17 +71,17 @@ Extract a collection of values from positions which depend on the current positi
 ```ts
 export function experiment<F extends URIS3>(
   F: Functor3<F>
-): <U, L, S, A>(wa: Store<S, A>, f: (s: S) => Type3<F, U, L, S>) => Type3<F, U, L, A>
+): <U, L, S>(f: (s: S) => Type3<F, U, L, S>) => <A>(wa: Store<S, A>) => Type3<F, U, L, A>
 export function experiment<F extends URIS2>(
   F: Functor2<F>
-): <L, S, A>(wa: Store<S, A>, f: (s: S) => Type2<F, L, S>) => Type2<F, L, A>
+): <L, S>(f: (s: S) => Type2<F, L, S>) => <A>(wa: Store<S, A>) => Type2<F, L, A>
 export function experiment<F extends URIS2, L>(
   F: Functor2C<F, L>
-): <S, A>(wa: Store<S, A>, f: (s: S) => Type2<F, L, S>) => Type2<F, L, A>
+): <S>(f: (s: S) => Type2<F, L, S>) => <A>(wa: Store<S, A>) => Type2<F, L, A>
 export function experiment<F extends URIS>(
   F: Functor1<F>
-): <S, A>(wa: Store<S, A>, f: (s: S) => Type<F, S>) => Type<F, A>
-export function experiment<F>(F: Functor<F>): <S, A>(wa: Store<S, A>, f: (s: S) => HKT<F, S>) => HKT<F, A> { ... }
+): <S>(f: (s: S) => Type<F, S>) => <A>(wa: Store<S, A>) => Type<F, A>
+export function experiment<F>(F: Functor<F>): <S>(f: (s: S) => HKT<F, S>) => <A>(wa: Store<S, A>) => HKT<F, A> { ... }
 ```
 
 Added in v2.0.0
@@ -93,7 +93,7 @@ Extract a value from a position which depends on the current position
 **Signature**
 
 ```ts
-export function peeks<S, A>(wa: Store<S, A>, f: Endomorphism<S>): A { ... }
+export function peeks<S>(f: Endomorphism<S>): <A>(wa: Store<S, A>) => A { ... }
 ```
 
 Added in v2.0.0
@@ -105,7 +105,7 @@ Reposition the focus at the specified position
 **Signature**
 
 ```ts
-export function seek<S, A>(wa: Store<S, A>, s: S): Store<S, A> { ... }
+export function seek<S>(s: S): <A>(wa: Store<S, A>) => Store<S, A> { ... }
 ```
 
 Added in v2.0.0
@@ -117,7 +117,7 @@ Reposition the focus at the specified position, which depends on the current pos
 **Signature**
 
 ```ts
-export function seeks<S, A>(wa: Store<S, A>, f: Endomorphism<S>): Store<S, A> { ... }
+export function seeks<S>(f: Endomorphism<S>): <A>(wa: Store<S, A>) => Store<S, A> { ... }
 ```
 
 Added in v2.0.0
diff --git a/docs/modules/TaskEither.ts.md b/docs/modules/TaskEither.ts.md
index 943eee46..7c2ac30c 100644
--- a/docs/modules/TaskEither.ts.md
+++ b/docs/modules/TaskEither.ts.md
@@ -95,7 +95,10 @@ Added in v2.0.0
 **Signature**
 
 ```ts
-export const  = ...
+export const fold: <L, A, R>(
+  onLeft: (l: L) => Task<R>,
+  onRight: (a: A) => Task<R>
+) => (ma: TaskEither<L, A>) => Task<R> = ...
 ```
 
 Added in v2.0.0
@@ -125,7 +128,7 @@ Added in v2.0.0
 **Signature**
 
 ```ts
-export const getOrElse: <L, A>(ma: TaskEither<L, A>, f: (l: L) => Task<A>) => Task<A> = ...
+export const getOrElse: <L, A>(f: (l: L) => Task<A>) => (ma: TaskEither<L, A>) => Task<A> = ...
 ```
 
 Added in v2.0.0
@@ -155,7 +158,7 @@ Added in v2.0.0
 **Signature**
 
 ```ts
-export const orElse: <L, A, M>(ma: TaskEither<L, A>, f: (l: L) => TaskEither<M, A>) => TaskEither<M, A> = ...
+export const orElse: <L, A, M>(f: (l: L) => TaskEither<M, A>) => (ma: TaskEither<L, A>) => TaskEither<M, A> = ...
 ```
 
 Added in v2.0.0
@@ -218,11 +221,13 @@ Added in v2.0.0
 
 ```ts
 export function filterOrElse<L, A, B extends A>(
-  ma: TaskEither<L, A>,
-  p: Refinement<A, B>,
+  predicate: Refinement<A, B>,
+  zero: (a: A) => L
+): (ma: TaskEither<L, A>) => TaskEither<L, B>
+export function filterOrElse<L, A>(
+  predicate: Predicate<A>,
   zero: (a: A) => L
-): TaskEither<L, B>
-export function filterOrElse<L, A>(ma: TaskEither<L, A>, p: Predicate<A>, zero: (a: A) => L): TaskEither<L, A> { ... }
+): (ma: TaskEither<L, A>) => TaskEither<L, A> { ... }
 ```
 
 Added in v2.0.0
diff --git a/docs/modules/These.ts.md b/docs/modules/These.ts.md
index 729593ef..11292b07 100644
--- a/docs/modules/These.ts.md
+++ b/docs/modules/These.ts.md
@@ -125,11 +125,10 @@ Added in v2.0.0
 
 ```ts
 export function fold<L, A, R>(
-  fa: These<L, A>,
   onLeft: (l: L) => R,
   onRight: (a: A) => R,
   onBoth: (l: L, a: A) => R
-): R { ... }
+): (fa: These<L, A>) => R { ... }
 ```
 
 Added in v2.0.0
@@ -391,7 +390,7 @@ Added in v2.0.0
 **Signature**
 
 ```ts
-export function toTuple<L, A>(fa: These<L, A>, l: L, a: A): [L, A] { ... }
+export function toTuple<L, A>(l: L, a: A): (fa: These<L, A>) => [L, A] { ... }
 ```
 
 **Example**
@@ -399,9 +398,9 @@ export function toTuple<L, A>(fa: These<L, A>, l: L, a: A): [L, A] { ... }
 ```ts
 import { toTuple, left, right, both } from 'fp-ts/lib/These'
 
-assert.deepStrictEqual(toTuple(left('b'), 'a', 1), ['b', 1])
-assert.deepStrictEqual(toTuple(right(2), 'a', 1), ['a', 2])
-assert.deepStrictEqual(toTuple(both('b', 2), 'a', 1), ['b', 2])
+assert.deepStrictEqual(toTuple('a', 1)(left('b')), ['b', 1])
+assert.deepStrictEqual(toTuple('a', 1)(right(2)), ['a', 2])
+assert.deepStrictEqual(toTuple('a', 1)(both('b', 2)), ['b', 2])
 ```
 
 Added in v2.0.0
diff --git a/docs/modules/Traced.ts.md b/docs/modules/Traced.ts.md
index 7c28b66b..da0d34cd 100644
--- a/docs/modules/Traced.ts.md
+++ b/docs/modules/Traced.ts.md
@@ -69,7 +69,7 @@ Apply a function to the current position
 **Signature**
 
 ```ts
-export function censor<P, A>(wa: Traced<P, A>, f: (p: P) => P): Traced<P, A> { ... }
+export function censor<P>(f: (p: P) => P): <A>(wa: Traced<P, A>) => Traced<P, A> { ... }
 ```
 
 Added in v2.0.0
@@ -103,7 +103,7 @@ Get a value which depends on the current position
 **Signature**
 
 ```ts
-export function listens<P, A, B>(wa: Traced<P, A>, f: (p: P) => B): Traced<P, [A, B]> { ... }
+export function listens<P, B>(f: (p: P) => B): <A>(wa: Traced<P, A>) => Traced<P, [A, B]> { ... }
 ```
 
 Added in v2.0.0
diff --git a/docs/modules/Tree.ts.md b/docs/modules/Tree.ts.md
index ca92d3aa..2fb98901 100644
--- a/docs/modules/Tree.ts.md
+++ b/docs/modules/Tree.ts.md
@@ -94,7 +94,7 @@ Neat 2-dimensional drawing of a forest
 **Signature**
 
 ```ts
-export const drawForest = (forest: Forest<string>): string => ...
+export function drawForest(forest: Forest<string>): string { ... }
 ```
 
 Added in v2.0.0
@@ -106,7 +106,7 @@ Neat 2-dimensional drawing of a tree
 **Signature**
 
 ```ts
-export const drawTree = (tree: Tree<string>): string => ...
+export function drawTree(tree: Tree<string>): string { ... }
 ```
 
 **Example**
@@ -176,7 +176,7 @@ Build a tree from a seed value
 **Signature**
 
 ```ts
-export const unfoldForest = <A, B>(bs: Array<B>, f: (b: B) => [A, Array<B>]): Forest<A> => ...
+export function unfoldForest<A, B>(bs: Array<B>, f: (b: B) => [A, Array<B>]): Forest<A> { ... }
 ```
 
 Added in v2.0.0
@@ -214,7 +214,7 @@ Build a tree from a seed value
 **Signature**
 
 ```ts
-export const unfoldTree = <A, B>(b: B, f: (b: B) => [A, Array<B>]): Tree<A> => ...
+export function unfoldTree<A, B>(b: B, f: (b: B) => [A, Array<B>]): Tree<A> { ... }
 ```
 
 Added in v2.0.0
diff --git a/docs/modules/Writer.ts.md b/docs/modules/Writer.ts.md
index bdd705a8..858dffe8 100644
--- a/docs/modules/Writer.ts.md
+++ b/docs/modules/Writer.ts.md
@@ -72,7 +72,7 @@ Modify the final accumulator value by applying a function
 **Signature**
 
 ```ts
-export function censor<W, A>(fa: Writer<W, A>, f: (w: W) => W): Writer<W, A> { ... }
+export function censor<W>(f: (w: W) => W): <A>(fa: Writer<W, A>) => Writer<W, A> { ... }
 ```
 
 Added in v2.0.0
@@ -126,7 +126,7 @@ Projects a value from modifications made to the accumulator during an action
 **Signature**
 
 ```ts
-export function listens<W, A, B>(fa: Writer<W, A>, f: (w: W) => B): Writer<W, [A, B]> { ... }
+export function listens<W, B>(f: (w: W) => B): <A>(fa: Writer<W, A>) => Writer<W, [A, B]> { ... }
 ```
 
 Added in v2.0.0
diff --git a/dtslint/ts3.4/index.ts b/dtslint/ts3.4/index.ts
index 6411df6b..c2220c18 100644
--- a/dtslint/ts3.4/index.ts
+++ b/dtslint/ts3.4/index.ts
@@ -145,14 +145,6 @@ Apv.getApplicativeComposition(Re.reader, applicativeValidation).map // $ExpectTy
 
 C.const_.contramap(C.make<boolean>(true), (s: string) => s.length) // $ExpectType Const<boolean, string>
 
-//
-// OptionT
-//
-
-// Monad2C
-
-OT.getOptionM(Th.getMonad(A.getMonoid<string>())) // $ExpectType OptionM2C<"These", string[]>
-
 //
 // TaskEither
 //
diff --git a/src/Either.ts b/src/Either.ts
index b9b82198..b548d56b 100644
--- a/src/Either.ts
+++ b/src/Either.ts
@@ -175,8 +175,8 @@ export function tryCatch<L, A>(f: Lazy<A>, onError: (e: unknown) => L): Either<L
 /**
  * @since 2.0.0
  */
-export function fold<L, A, R>(ma: Either<L, A>, onLeft: (l: L) => R, onRight: (a: A) => R): R {
-  return isLeft(ma) ? onLeft(ma.left) : onRight(ma.right)
+export function fold<L, A, R>(onLeft: (l: L) => R, onRight: (a: A) => R): (ma: Either<L, A>) => R {
+  return ma => (isLeft(ma) ? onLeft(ma.left) : onRight(ma.right))
 }
 
 /**
@@ -285,28 +285,34 @@ export function swap<L, A>(ma: Either<L, A>): Either<A, L> {
 /**
  * @since 2.0.0
  */
-export function orElse<L, A, M>(ma: Either<L, A>, f: (l: L) => Either<M, A>): Either<M, A> {
-  return isLeft(ma) ? f(ma.left) : ma
+export function orElse<L, A, M>(f: (l: L) => Either<M, A>): (ma: Either<L, A>) => Either<M, A> {
+  return ma => (isLeft(ma) ? f(ma.left) : ma)
 }
 
 /**
  * @since 2.0.0
  */
-export function getOrElse<L, A>(ma: Either<L, A>, f: (l: L) => A): A {
-  return isLeft(ma) ? f(ma.left) : ma.right
+export function getOrElse<L, A>(f: (l: L) => A): (ma: Either<L, A>) => A {
+  return ma => (isLeft(ma) ? f(ma.left) : ma.right)
+}
+
+/**
+ * @since 2.0.0
+ */
+export function elem<A>(E: Eq<A>): <L>(a: A, ma: Either<L, A>) => boolean {
+  return (a, ma) => (isLeft(ma) ? false : E.equals(a, ma.right))
 }
 
 /**
  * @since 2.0.0
  */
 export function filterOrElse<L, A, B extends A>(
-  ma: Either<L, A>,
   refinement: Refinement<A, B>,
   zero: (a: A) => L
-): Either<L, B>
-export function filterOrElse<L, A>(ma: Either<L, A>, predicate: Predicate<A>, zero: (a: A) => L): Either<L, A>
-export function filterOrElse<L, A>(ma: Either<L, A>, predicate: Predicate<A>, zero: (a: A) => L): Either<L, A> {
-  return isLeft(ma) ? ma : predicate(ma.right) ? ma : left(zero(ma.right))
+): (ma: Either<L, A>) => Either<L, B>
+export function filterOrElse<L, A>(predicate: Predicate<A>, zero: (a: A) => L): (ma: Either<L, A>) => Either<L, A>
+export function filterOrElse<L, A>(predicate: Predicate<A>, zero: (a: A) => L): (ma: Either<L, A>) => Either<L, A> {
+  return ma => (isLeft(ma) ? ma : predicate(ma.right) ? ma : left(zero(ma.right)))
 }
 
 /**
@@ -341,16 +347,12 @@ export function stringifyJSON<L>(u: unknown, onError: (reason: unknown) => L): E
   return tryCatch(() => JSON.stringify(u), onError)
 }
 
-//
-// instances
-//
-
 const map = <L, A, B>(ma: Either<L, A>, f: (a: A) => B): Either<L, B> => {
   return isLeft(ma) ? ma : right(f(ma.right))
 }
 
 const ap = <L, A, B>(mab: Either<L, (a: A) => B>, ma: Either<L, A>): Either<L, B> => {
-  return isLeft(mab) ? mab : fold<L, A, Either<L, B>>(ma, left, a => right(mab.right(a)))
+  return isLeft(mab) ? mab : isLeft(ma) ? ma : right(mab.right(ma.right))
 }
 
 const chain = <L, A, B>(ma: Either<L, A>, f: (a: A) => Either<L, B>): Either<L, B> => {
@@ -462,7 +464,8 @@ export function getFilterable<L>(M: Monoid<L>): Filterable2C<URI, L> {
     return isLeft(ma) ? ma : fromOption(f(ma.right), onNone)
   }
 
-  const filter = <A>(ma: Either<L, A>, p: Predicate<A>): Either<L, A> => filterOrElse(ma, p, () => M.empty)
+  const filter = <A>(ma: Either<L, A>, predicate: Predicate<A>): Either<L, A> =>
+    isLeft(ma) ? ma : predicate(ma.right) ? ma : left(M.empty)
 
   return {
     ...C,
@@ -533,7 +536,7 @@ export const either: Monad2<URI> &
   sequence,
   bimap,
   mapLeft: (ma, f) => (isLeft(ma) ? left(f(ma.left)) : ma),
-  alt: orElse,
+  alt: (fx, fy) => (isLeft(fx) ? fy() : fx),
   extend,
   chainRec
 }
diff --git a/src/EitherT.ts b/src/EitherT.ts
index 576dc335..61ced7da 100644
--- a/src/EitherT.ts
+++ b/src/EitherT.ts
@@ -18,11 +18,15 @@ export interface EitherT<M, L, A> extends HKT<M, Either<L, A>> {}
  */
 export interface EitherM<M> extends ApplicativeComposition02<M, URI> {
   readonly chain: <L, A, B>(ma: EitherT<M, L, A>, f: (a: A) => EitherT<M, L, B>) => EitherT<M, L, B>
-  readonly fold: <L, A, R>(ma: EitherT<M, L, A>, onLeft: (l: L) => HKT<M, R>, onRight: (a: A) => HKT<M, R>) => HKT<M, R>
+  readonly alt: <L, A>(fx: EitherT<M, L, A>, f: () => EitherT<M, L, A>) => EitherT<M, L, A>
+  readonly fold: <L, A, R>(
+    onLeft: (l: L) => HKT<M, R>,
+    onRight: (a: A) => HKT<M, R>
+  ) => (ma: EitherT<M, L, A>) => HKT<M, R>
   readonly bimap: <L, A, N, B>(ma: EitherT<M, L, A>, f: (l: L) => N, g: (a: A) => B) => EitherT<M, N, B>
   readonly mapLeft: <L, A, N>(ma: EitherT<M, L, A>, f: (l: L) => N) => EitherT<M, N, A>
-  readonly getOrElse: <L, A>(ma: EitherT<M, L, A>, f: (l: L) => HKT<M, A>) => HKT<M, A>
-  readonly orElse: <L, A, N>(ma: EitherT<M, L, A>, f: (l: L) => EitherT<M, N, A>) => EitherT<M, N, A>
+  readonly getOrElse: <L, A>(f: (l: L) => HKT<M, A>) => (ma: EitherT<M, L, A>) => HKT<M, A>
+  readonly orElse: <L, A, N>(f: (l: L) => EitherT<M, N, A>) => (ma: EitherT<M, L, A>) => EitherT<M, N, A>
   readonly swap: <L, A>(ma: EitherT<M, L, A>) => EitherT<M, A, L>
   readonly rightM: <L, A>(ma: HKT<M, A>) => EitherT<M, L, A>
   readonly leftM: <L, A>(ml: HKT<M, L>) => EitherT<M, L, A>
@@ -44,15 +48,15 @@ export type EitherT1<M extends URIS, L, A> = Type<M, Either<L, A>>
  */
 export interface EitherM1<M extends URIS> extends ApplicativeComposition12<M, URI> {
   readonly chain: <L, A, B>(ma: EitherT1<M, L, A>, f: (a: A) => EitherT1<M, L, B>) => EitherT1<M, L, B>
+  readonly alt: <L, A>(fx: EitherT1<M, L, A>, f: () => EitherT1<M, L, A>) => EitherT1<M, L, A>
   readonly fold: <L, A, R>(
-    ma: EitherT1<M, L, A>,
     onLeft: (l: L) => Type<M, R>,
     onRight: (a: A) => Type<M, R>
-  ) => Type<M, R>
+  ) => (ma: EitherT1<M, L, A>) => Type<M, R>
   readonly bimap: <L, A, N, B>(ma: EitherT1<M, L, A>, f: (l: L) => N, g: (a: A) => B) => EitherT1<M, N, B>
   readonly mapLeft: <L, A, N>(ma: EitherT1<M, L, A>, f: (l: L) => N) => EitherT1<M, N, A>
-  readonly getOrElse: <L, A>(ma: EitherT1<M, L, A>, f: (l: L) => Type<M, A>) => Type<M, A>
-  readonly orElse: <L, A, N>(ma: EitherT1<M, L, A>, f: (l: L) => EitherT1<M, N, A>) => EitherT1<M, N, A>
+  readonly getOrElse: <L, A>(f: (l: L) => Type<M, A>) => (ma: EitherT1<M, L, A>) => Type<M, A>
+  readonly orElse: <L, A, N>(f: (l: L) => EitherT1<M, N, A>) => (ma: EitherT1<M, L, A>) => EitherT1<M, N, A>
   readonly swap: <L, A>(ma: EitherT1<M, L, A>) => EitherT1<M, A, L>
   readonly rightM: <L, A>(ma: Type<M, A>) => EitherT1<M, L, A>
   readonly leftM: <L, A>(ml: Type<M, L>) => EitherT1<M, L, A>
@@ -74,15 +78,17 @@ export type EitherT2<M extends URIS2, LM, L, A> = Type2<M, LM, Either<L, A>>
  */
 export interface EitherM2<M extends URIS2> extends ApplicativeComposition22<M, URI> {
   readonly chain: <LM, L, A, B>(ma: EitherT2<M, LM, L, A>, f: (a: A) => EitherT2<M, LM, L, B>) => EitherT2<M, LM, L, B>
+  readonly alt: <LM, L, A>(fx: EitherT2<M, LM, L, A>, f: () => EitherT2<M, LM, L, A>) => EitherT2<M, LM, L, A>
   readonly fold: <LM, L, A, R>(
-    ma: EitherT2<M, LM, L, A>,
     onLeft: (l: L) => Type2<M, LM, R>,
     onRight: (a: A) => Type2<M, LM, R>
-  ) => Type2<M, LM, R>
+  ) => (ma: EitherT2<M, LM, L, A>) => Type2<M, LM, R>
   readonly bimap: <LM, L, A, N, B>(ma: EitherT2<M, LM, L, A>, f: (l: L) => N, g: (a: A) => B) => EitherT2<M, LM, N, B>
   readonly mapLeft: <LM, L, A, N>(ma: EitherT2<M, LM, L, A>, f: (l: L) => N) => EitherT2<M, LM, N, A>
-  readonly getOrElse: <LM, L, A>(ma: EitherT2<M, LM, L, A>, f: (l: L) => Type2<M, LM, A>) => Type2<M, LM, A>
-  readonly orElse: <LM, L, A, N>(ma: EitherT2<M, LM, L, A>, f: (l: L) => EitherT2<M, LM, N, A>) => EitherT2<M, LM, N, A>
+  readonly getOrElse: <LM, L, A>(f: (l: L) => Type2<M, LM, A>) => (ma: EitherT2<M, LM, L, A>) => Type2<M, LM, A>
+  readonly orElse: <LM, L, A, N>(
+    f: (l: L) => EitherT2<M, LM, N, A>
+  ) => (ma: EitherT2<M, LM, L, A>) => EitherT2<M, LM, N, A>
   readonly swap: <LM, L, A>(ma: EitherT2<M, LM, L, A>) => EitherT2<M, LM, A, L>
   readonly rightM: <LM, L, A>(ma: Type2<M, LM, A>) => EitherT2<M, LM, L, A>
   readonly leftM: <LM, L, A>(ml: Type2<M, LM, L>) => EitherT2<M, LM, L, A>
@@ -111,11 +117,12 @@ export function getEitherM<M>(M: Monad<M>): EitherM<M> {
   return {
     ...A,
     chain,
-    fold: (ma, onLeft, onRight) => M.chain(ma, e => fold(e, onLeft, onRight)),
+    alt: (fx, fy) => M.chain(fx, e => (isLeft(e) ? fy() : A.of(e.right))),
+    fold: (onLeft, onRight) => ma => M.chain(ma, fold(onLeft, onRight)),
     bimap: (ma, f, g) => M.map(ma, e => either.bimap(e, f, g)),
     mapLeft: (ma, f) => M.map(ma, e => either.mapLeft(e, f)),
-    getOrElse: (ma, onLeft) => M.chain(ma, e => fold(e, onLeft, M.of)),
-    orElse: (ma, f) => M.chain(ma, e => fold(e, f, a => A.of(a))),
+    getOrElse: onLeft => ma => M.chain(ma, fold(onLeft, M.of)),
+    orElse: f => ma => M.chain(ma, fold(f, a => A.of(a))),
     swap: ma => M.map(ma, swap),
     rightM: ma => M.map(ma, right),
     leftM: ml => M.map(ml, left),
@@ -126,7 +133,7 @@ export function getEitherM<M>(M: Monad<M>): EitherM<M> {
       release: (a: A, e: Either<L, B>) => EitherT<M, L, void>
     ): EitherT<M, L, B> =>
       chain(acquire, a =>
-        chain(M.map(use(a), right), e => chain(release(a, e), () => fold<L, B, EitherT<M, L, B>>(e, _left, A.of)))
+        chain(M.map(use(a), right), e => chain(release(a, e), () => (isLeft(e) ? _left(e.left) : A.of(e.right))))
       )
   }
 }
diff --git a/src/IOEither.ts b/src/IOEither.ts
index 7df80ddf..d067fac9 100644
--- a/src/IOEither.ts
+++ b/src/IOEither.ts
@@ -85,30 +85,30 @@ export function fromPredicate<L, A>(predicate: Predicate<A>, onFalse: (a: A) =>
 /**
  * @since 2.0.0
  */
-export const fold: <L, A, R>(ma: IOEither<L, A>, onLeft: (l: L) => IO<R>, onRight: (a: A) => IO<R>) => IO<R> = T.fold
+export const fold: <L, A, R>(onLeft: (l: L) => IO<R>, onRight: (a: A) => IO<R>) => (ma: IOEither<L, A>) => IO<R> =
+  T.fold
 
 /**
  * @since 2.0.0
  */
-export const getOrElse: <L, A>(ma: IOEither<L, A>, f: (l: L) => IO<A>) => IO<A> = T.getOrElse
+export const getOrElse: <L, A>(f: (l: L) => IO<A>) => (ma: IOEither<L, A>) => IO<A> = T.getOrElse
 
 /**
  * @since 2.0.0
  */
 export function filterOrElse<L, A, B extends A>(
-  ma: IOEither<L, A>,
   p: Refinement<A, B>,
   zero: (a: A) => L
-): IOEither<L, B>
-export function filterOrElse<L, A>(ma: IOEither<L, A>, p: Predicate<A>, zero: (a: A) => L): IOEither<L, A>
-export function filterOrElse<L, A>(ma: IOEither<L, A>, p: Predicate<A>, zero: (a: A) => L): IOEither<L, A> {
-  return io.map(ma, e => E.filterOrElse(e, p, zero))
+): (ma: IOEither<L, A>) => IOEither<L, B>
+export function filterOrElse<L, A>(p: Predicate<A>, zero: (a: A) => L): (ma: IOEither<L, A>) => IOEither<L, A>
+export function filterOrElse<L, A>(p: Predicate<A>, zero: (a: A) => L): (ma: IOEither<L, A>) => IOEither<L, A> {
+  return ma => io.map(ma, E.filterOrElse(p, zero))
 }
 
 /**
  * @since 2.0.0
  */
-export const orElse: <L, A, M>(ma: IOEither<L, A>, f: (l: L) => IOEither<M, A>) => IOEither<M, A> = T.orElse
+export const orElse: <L, A, M>(f: (l: L) => IOEither<M, A>) => (ma: IOEither<L, A>) => IOEither<M, A> = T.orElse
 
 /**
  * @since 2.0.0
@@ -172,6 +172,6 @@ export const ioEither: Monad2<URI> & Bifunctor2<URI> & Alt2<URI> & MonadIO2<URI>
   of: right,
   ap: T.ap,
   chain: T.chain,
-  alt: orElse,
+  alt: T.alt,
   fromIO: rightIO
 }
diff --git a/src/Option.ts b/src/Option.ts
index 0c0c836f..99e20e07 100644
--- a/src/Option.ts
+++ b/src/Option.ts
@@ -42,8 +42,8 @@
  *
  * const value1 = head(['foo', 'bar']) // some('foo)
  * const value2 = head([]) // none
- * getOrElse(value1, 'No value') // 'foo'
- * getOrElse(value2, 'No value') // 'No value'
+ * getOrElse(() => 'No value')(value1) // 'foo'
+ * getOrElse(() => 'No value')(value2) // 'No value'
  * ```
  *
  * Checking whether option has value:
@@ -62,8 +62,8 @@
  *
  * const x: Option<number> = some(3)
  * const y: Option<number> = none
- * fold(x, 1, n => n * 3) // 9
- * fold(y, 1, n => n * 3) // 1
+ * fold(1, n => n * 3)(x) // 9
+ * fold(1, n => n * 3)(y) // 1
  * ```
  *
  * You can chain several possibly failing computations using the `chain` function
@@ -168,8 +168,8 @@ export function isNone<A>(fa: Option<A>): fa is None {
 /**
  * @since 2.0.0
  */
-export function fold<A, R>(ma: Option<A>, onNone: () => R, onSome: (a: A) => R): R {
-  return isNone(ma) ? onNone() : onSome(ma.value)
+export function fold<A, R>(onNone: () => R, onSome: (a: A) => R): (ma: Option<A>) => R {
+  return ma => (isNone(ma) ? onNone() : onSome(ma.value))
 }
 
 /**
@@ -213,8 +213,8 @@ export function toUndefined<A>(ma: Option<A>): A | undefined {
 /**
  * @since 2.0.0
  */
-export function getOrElse<A>(ma: Option<A>, f: () => A): A {
-  return isNone(ma) ? f() : ma.value
+export function getOrElse<A>(f: () => A): (ma: Option<A>) => A {
+  return ma => (isNone(ma) ? f() : ma.value)
 }
 
 /**
@@ -227,8 +227,8 @@ export function elem<A>(E: Eq<A>): (a: A, ma: Option<A>) => boolean {
 /**
  * @since 2.0.0
  */
-export function exists<A>(ma: Option<A>, predicate: Predicate<A>): boolean {
-  return isNone(ma) ? false : predicate(ma.value)
+export function exists<A>(predicate: Predicate<A>): (ma: Option<A>) => boolean {
+  return ma => (isNone(ma) ? false : predicate(ma.value))
 }
 
 /**
@@ -315,8 +315,8 @@ export function getRefinement<A, B extends A>(getOption: (a: A) => Option<B>): R
 /**
  * @since 2.0.0
  */
-export function mapNullable<A, B>(ma: Option<A>, f: (a: A) => B | null | undefined): Option<B> {
-  return isNone(ma) ? none : fromNullable(f(ma.value))
+export function mapNullable<A, B>(f: (a: A) => B | null | undefined): (ma: Option<A>) => Option<B> {
+  return ma => (isNone(ma) ? none : fromNullable(f(ma.value)))
 }
 
 /**
@@ -521,13 +521,11 @@ const map = <A, B>(ma: Option<A>, f: (a: A) => B): Option<B> => {
 }
 
 const separate = <RL, RR>(ma: Option<Either<RL, RR>>): Separated<Option<RL>, Option<RR>> => {
-  return getOrElse(
-    map(ma, e => ({
-      left: getLeft(e),
-      right: getRight(e)
-    })),
-    () => defaultSeparate
-  )
+  const o = map(ma, e => ({
+    left: getLeft(e),
+    right: getRight(e)
+  }))
+  return isNone(o) ? defaultSeparate : o.value
 }
 
 const wither = <F>(F: Applicative<F>) => <A, B>(fa: Option<A>, f: (a: A) => HKT<F, Option<B>>): HKT<F, Option<B>> =>
@@ -537,19 +535,18 @@ const wilt = <F>(F: Applicative<F>) => <RL, RR, A>(
   fa: Option<A>,
   f: (a: A) => HKT<F, Either<RL, RR>>
 ): HKT<F, Separated<Option<RL>, Option<RR>>> => {
-  return getOrElse(
-    map(fa, a =>
-      F.map(f(a), e => ({
-        left: getLeft(e),
-        right: getRight(e)
-      }))
-    ),
-    () =>
-      F.of({
+  const o = map(fa, a =>
+    F.map(f(a), e => ({
+      left: getLeft(e),
+      right: getRight(e)
+    }))
+  )
+  return isNone(o)
+    ? F.of({
         left: none,
         right: none
       })
-  )
+    : o.value
 }
 
 const zero = () => none
diff --git a/src/OptionT.ts b/src/OptionT.ts
index 07742d6d..160dcff9 100644
--- a/src/OptionT.ts
+++ b/src/OptionT.ts
@@ -2,12 +2,11 @@ import {
   ApplicativeComposition01,
   ApplicativeComposition11,
   ApplicativeComposition21,
-  ApplicativeComposition2C1,
   getApplicativeComposition
 } from './Applicative'
 import { HKT, Type, Type2, URIS, URIS2 } from './HKT'
-import { Monad, Monad1, Monad2, Monad2C } from './Monad'
-import { fold, isNone, none, Option, option, some, URI } from './Option'
+import { Monad, Monad1, Monad2 } from './Monad'
+import { fold, none, Option, option, some, URI } from './Option'
 
 /**
  * @since 2.0.0
@@ -19,8 +18,9 @@ export interface OptionT<M, A> extends HKT<M, Option<A>> {}
  */
 export interface OptionM<M> extends ApplicativeComposition01<M, URI> {
   readonly chain: <A, B>(ma: OptionT<M, A>, f: (a: A) => OptionT<M, B>) => OptionT<M, B>
-  readonly fold: <A, R>(ma: OptionT<M, A>, onNone: () => HKT<M, R>, onSome: (a: A) => HKT<M, R>) => HKT<M, R>
-  readonly getOrElse: <A>(ma: OptionT<M, A>, onNone: () => HKT<M, A>) => HKT<M, A>
+  readonly alt: <A>(fx: OptionT<M, A>, fy: () => OptionT<M, A>) => OptionT<M, A>
+  readonly fold: <A, R>(onNone: () => HKT<M, R>, onSome: (a: A) => HKT<M, R>) => (ma: OptionT<M, A>) => HKT<M, R>
+  readonly getOrElse: <A>(onNone: () => HKT<M, A>) => (ma: OptionT<M, A>) => HKT<M, A>
   readonly fromM: <A>(ma: HKT<M, A>) => OptionT<M, A>
   readonly fromOption: <A>(ma: Option<A>) => OptionT<M, A>
   readonly none: () => OptionT<M, never>
@@ -36,8 +36,9 @@ export type OptionT1<M extends URIS, A> = Type<M, Option<A>>
  */
 export interface OptionM1<M extends URIS> extends ApplicativeComposition11<M, URI> {
   readonly chain: <A, B>(ma: OptionT1<M, A>, f: (a: A) => OptionT1<M, B>) => OptionT1<M, B>
-  readonly fold: <A, R>(ma: OptionT1<M, A>, onNone: () => Type<M, R>, onSome: (a: A) => Type<M, R>) => Type<M, R>
-  readonly getOrElse: <A>(ma: OptionT1<M, A>, onNone: () => Type<M, A>) => Type<M, A>
+  readonly alt: <A>(fx: OptionT1<M, A>, fy: () => OptionT1<M, A>) => OptionT1<M, A>
+  readonly fold: <A, R>(onNone: () => Type<M, R>, onSome: (a: A) => Type<M, R>) => (ma: OptionT1<M, A>) => Type<M, R>
+  readonly getOrElse: <A>(onNone: () => Type<M, A>) => (ma: OptionT1<M, A>) => Type<M, A>
   readonly fromM: <A>(ma: Type<M, A>) => OptionT1<M, A>
   readonly fromOption: <A>(ma: Option<A>) => OptionT1<M, A>
   readonly none: () => OptionT1<M, never>
@@ -53,38 +54,21 @@ export type OptionT2<M extends URIS2, L, A> = Type2<M, L, Option<A>>
  */
 export interface OptionM2<M extends URIS2> extends ApplicativeComposition21<M, URI> {
   readonly chain: <L, A, B>(ma: OptionT2<M, L, A>, f: (a: A) => OptionT2<M, L, B>) => OptionT2<M, L, B>
+  readonly alt: <L, A>(fx: OptionT2<M, L, A>, fy: () => OptionT2<M, L, A>) => OptionT2<M, L, A>
   readonly fold: <L, A, R>(
-    ma: OptionT2<M, L, A>,
     onNone: () => Type2<M, L, R>,
     onSome: (a: A) => Type2<M, L, R>
-  ) => Type2<M, L, R>
-  readonly getOrElse: <L, A>(ma: OptionT2<M, L, A>, onNone: () => Type2<M, L, A>) => Type2<M, L, A>
+  ) => (ma: OptionT2<M, L, A>) => Type2<M, L, R>
+  readonly getOrElse: <L, A>(onNone: () => Type2<M, L, A>) => (ma: OptionT2<M, L, A>) => Type2<M, L, A>
   readonly fromM: <L, A>(ma: Type2<M, L, A>) => OptionT2<M, L, A>
   readonly fromOption: <L, A>(ma: Option<A>) => OptionT2<M, L, A>
   readonly none: <L>() => OptionT2<M, L, never>
 }
 
-/**
- * @since 2.0.0
- */
-export interface OptionM2C<M extends URIS2, L> extends ApplicativeComposition2C1<M, URI, L> {
-  readonly chain: <A, B>(ma: OptionT2<M, L, A>, f: (a: A) => OptionT2<M, L, B>) => OptionT2<M, L, B>
-  readonly fold: <A, R>(
-    ma: OptionT2<M, L, A>,
-    onNone: () => Type2<M, L, R>,
-    onSome: (a: A) => Type2<M, L, R>
-  ) => Type2<M, L, R>
-  readonly getOrElse: <A>(ma: OptionT2<M, L, A>, onNone: () => Type2<M, L, A>) => Type2<M, L, A>
-  readonly fromM: <A>(ma: Type2<M, L, A>) => OptionT2<M, L, A>
-  readonly fromOption: <A>(ma: Option<A>) => OptionT2<M, L, A>
-  readonly none: () => OptionT2<M, L, never>
-}
-
 /**
  * @since 2.0.0
  */
 export function getOptionM<M extends URIS2>(M: Monad2<M>): OptionM2<M>
-export function getOptionM<M extends URIS2, L>(M: Monad2C<M, L>): OptionM2C<M, L>
 export function getOptionM<M extends URIS>(M: Monad1<M>): OptionM1<M>
 export function getOptionM<M>(M: Monad<M>): OptionM<M>
 export function getOptionM<M>(M: Monad<M>): OptionM<M> {
@@ -93,11 +77,12 @@ export function getOptionM<M>(M: Monad<M>): OptionM<M> {
 
   return {
     ...A,
-    chain: (ma, f) => M.chain(ma, o => (isNone(o) ? fnone : f(o.value))),
-    fold: (ma, onNone, onSome) => M.chain(ma, o => fold(o, onNone, onSome)),
-    getOrElse: (ma, onNone) => M.chain(ma, e => fold(e, onNone, M.of)),
+    chain: (ma, f) => M.chain(ma, fold(() => fnone, f)),
+    alt: (fx, fy) => M.chain(fx, fold(fy, a => M.of(some(a)))),
+    fold: (onNone, onSome) => ma => M.chain(ma, fold(onNone, onSome)),
+    getOrElse: onNone => ma => M.chain(ma, fold(onNone, M.of)),
     fromM: ma => M.map(ma, some),
-    fromOption: o => M.of(o),
+    fromOption: M.of,
     none: () => fnone
   }
 }
diff --git a/src/Reader.ts b/src/Reader.ts
index ca1889d9..10b4fa85 100644
--- a/src/Reader.ts
+++ b/src/Reader.ts
@@ -54,7 +54,7 @@ export const asks: <E, A>(f: (e: E) => A) => Reader<E, A> = T.asks
  *
  * @since 2.0.0
  */
-export const local: <E, A, D>(ma: Reader<E, A>, f: (d: D) => E) => Reader<D, A> = T.local
+export const local: <D, E>(f: (d: D) => E) => <A>(ma: Reader<E, A>) => Reader<D, A> = T.local
 
 /**
  * @since 2.0.0
@@ -76,11 +76,11 @@ export function getMonoid<E, A>(M: Monoid<A>): Monoid<Reader<E, A>> {
 }
 
 function left<A, B, C>(pab: Reader<A, B>): Reader<E.Either<A, C>, E.Either<B, C>> {
-  return e => E.fold<A, C, E.Either<B, C>>(e, a => E.left(pab(a)), E.right)
+  return E.fold<A, C, E.Either<B, C>>(a => E.left(pab(a)), E.right)
 }
 
 function right<A, B, C>(pbc: Reader<B, C>): Reader<E.Either<A, B>, E.Either<A, C>> {
-  return e => E.fold<A, B, E.Either<A, C>>(e, E.left, b => E.right(pbc(b)))
+  return E.fold<A, B, E.Either<A, C>>(E.left, b => E.right(pbc(b)))
 }
 
 /**
diff --git a/src/ReaderT.ts b/src/ReaderT.ts
index 759587b2..b18d3a97 100644
--- a/src/ReaderT.ts
+++ b/src/ReaderT.ts
@@ -19,7 +19,7 @@ export interface ReaderM<M> {
   readonly chain: <E, A, B>(ma: ReaderT<M, E, A>, f: (a: A) => ReaderT<M, E, B>) => ReaderT<M, E, B>
   readonly ask: <E>() => ReaderT<M, E, E>
   readonly asks: <E, A>(f: (e: E) => A) => ReaderT<M, E, A>
-  readonly local: <E, A, D>(ma: ReaderT<M, E, A>, f: (d: D) => E) => ReaderT<M, D, A>
+  readonly local: <D, E>(f: (d: D) => E) => <A>(ma: ReaderT<M, E, A>) => ReaderT<M, D, A>
   readonly fromReader: <E, A>(ma: Reader<E, A>) => ReaderT<M, E, A>
   readonly fromM: <E, A>(ma: HKT<M, A>) => ReaderT<M, E, A>
 }
@@ -41,7 +41,7 @@ export interface ReaderM1<M extends URIS> {
   readonly chain: <E, A, B>(ma: ReaderT1<M, E, A>, f: (a: A) => ReaderT1<M, E, B>) => ReaderT1<M, E, B>
   readonly ask: <E>() => ReaderT1<M, E, E>
   readonly asks: <E, A>(f: (e: E) => A) => ReaderT1<M, E, A>
-  readonly local: <E, A, D>(ma: ReaderT1<M, E, A>, f: (d: D) => E) => ReaderT1<M, D, A>
+  readonly local: <D, E>(f: (d: D) => E) => <A>(ma: ReaderT1<M, E, A>) => ReaderT1<M, D, A>
   readonly fromReader: <E, A>(ma: Reader<E, A>) => ReaderT1<M, E, A>
   readonly fromM: <E, A>(ma: Type<M, A>) => ReaderT1<M, E, A>
 }
@@ -63,7 +63,7 @@ export interface ReaderM2<M extends URIS2> {
   readonly chain: <E, L, A, B>(ma: ReaderT2<M, E, L, A>, f: (a: A) => ReaderT2<M, E, L, B>) => ReaderT2<M, E, L, B>
   readonly ask: <E, L>() => ReaderT2<M, E, L, E>
   readonly asks: <E, L, A>(f: (e: E) => A) => ReaderT2<M, E, L, A>
-  readonly local: <E, L, A, D>(ma: ReaderT2<M, E, L, A>, f: (d: D) => E) => ReaderT2<M, D, L, A>
+  readonly local: <D, E>(f: (d: D) => E) => <L, A>(ma: ReaderT2<M, E, L, A>) => ReaderT2<M, D, L, A>
   readonly fromReader: <E, L, A>(ma: Reader<E, A>) => ReaderT2<M, E, L, A>
   readonly fromM: <E, L, A>(ma: Type2<M, L, A>) => ReaderT2<M, E, L, A>
 }
@@ -91,7 +91,7 @@ export interface ReaderM3<M extends URIS3> {
   ) => ReaderT3<M, E, U, L, B>
   readonly ask: <E, U, L>() => ReaderT3<M, E, U, L, E>
   readonly asks: <E, U, L, A>(f: (e: E) => A) => ReaderT3<M, E, U, L, A>
-  readonly local: <E, U, L, A, D>(ma: ReaderT3<M, E, U, L, A>, f: (d: D) => E) => ReaderT3<M, D, U, L, A>
+  readonly local: <D, E>(f: (d: D) => E) => <U, L, A>(ma: ReaderT3<M, E, U, L, A>) => ReaderT3<M, D, U, L, A>
   readonly fromReader: <E, U, L, A>(ma: Reader<E, A>) => ReaderT3<M, E, U, L, A>
   readonly fromM: <E, U, L, A>(ma: Type3<M, U, L, A>) => ReaderT3<M, E, U, L, A>
 }
@@ -111,7 +111,7 @@ export function getReaderM<M>(M: Monad<M>): ReaderM<M> {
     chain: (ma, f) => e => M.chain(ma(e), a => f(a)(e)),
     ask: () => M.of,
     asks: f => e => M.map(M.of(e), f),
-    local: (ma, f) => d => ma(f(d)),
+    local: f => ma => d => ma(f(d)),
     fromReader: ma => e => M.of(ma(e)),
     fromM: ma => () => ma
   }
diff --git a/src/ReaderTaskEither.ts b/src/ReaderTaskEither.ts
index 465246c0..557b171d 100644
--- a/src/ReaderTaskEither.ts
+++ b/src/ReaderTaskEither.ts
@@ -1,7 +1,7 @@
 import { Alt3 } from './Alt'
 import { Bifunctor3 } from './Bifunctor'
 import { Either } from './Either'
-import { Predicate, Refinement } from './function'
+import { pipeOp, Predicate, Refinement } from './function'
 import { IO } from './IO'
 import { IOEither } from './IOEither'
 import { Monad3 } from './Monad'
@@ -148,31 +148,28 @@ export function fromPredicate<L, A>(
  * @since 2.0.0
  */
 export function fold<E, L, A, R>(
-  ma: ReaderTaskEither<E, L, A>,
   onLeft: (l: L) => Reader<E, Task<R>>,
   onRight: (a: A) => Reader<E, Task<R>>
-): Reader<E, Task<R>> {
-  return e => TE.fold(ma(e), l => onLeft(l)(e), a => onRight(a)(e))
+): (ma: ReaderTaskEither<E, L, A>) => Reader<E, Task<R>> {
+  return ma => e => pipeOp(ma(e), TE.fold(l => onLeft(l)(e), a => onRight(a)(e)))
 }
 
 /**
  * @since 2.0.0
  */
 export function getOrElse<E, L, A>(
-  ma: ReaderTaskEither<E, L, A>,
   onLeft: (l: L) => Reader<E, Task<A>>
-): Reader<E, Task<A>> {
-  return e => TE.getOrElse(ma(e), l => onLeft(l)(e))
+): (ma: ReaderTaskEither<E, L, A>) => Reader<E, Task<A>> {
+  return ma => e => TE.getOrElse<L, A>(l => onLeft(l)(e))(ma(e))
 }
 
 /**
  * @since 2.0.0
  */
 export function orElse<E, L, A, M>(
-  ma: ReaderTaskEither<E, L, A>,
   f: (l: L) => ReaderTaskEither<E, M, A>
-): ReaderTaskEither<E, M, A> {
-  return e => TE.orElse(ma(e), l => f(l)(e))
+): (ma: ReaderTaskEither<E, L, A>) => ReaderTaskEither<E, M, A> {
+  return ma => e => TE.orElse<L, A, M>(l => f(l)(e))(ma(e))
 }
 
 /**
@@ -188,7 +185,15 @@ export const asks: <E, A>(f: (e: E) => A) => ReaderTaskEither<E, never, A> = T.a
 /**
  * @since 2.0.0
  */
-export const local: <E, L, A, D>(ma: ReaderTaskEither<E, L, A>, f: (f: D) => E) => ReaderTaskEither<D, L, A> = T.local
+export const local: <D, E>(f: (f: D) => E) => <L, A>(ma: ReaderTaskEither<E, L, A>) => ReaderTaskEither<D, L, A> =
+  T.local
+
+const alt = <E, L, A>(
+  fx: ReaderTaskEither<E, L, A>,
+  fy: () => ReaderTaskEither<E, L, A>
+): ReaderTaskEither<E, L, A> => {
+  return e => TE.taskEither.alt(fx(e), () => fy()(e))
+}
 
 /**
  * @since 2.0.0
@@ -199,7 +204,7 @@ export const readerTaskEither: Monad3<URI> & Bifunctor3<URI> & Alt3<URI> & Monad
   of: right,
   ap: T.ap,
   chain: T.chain,
-  alt: orElse,
+  alt,
   bimap: (ma, f, g) => e => TE.taskEither.bimap(ma(e), f, g),
   mapLeft: (ma, f) => e => TE.taskEither.mapLeft(ma(e), f),
   fromIO: rightIO,
diff --git a/src/Store.ts b/src/Store.ts
index 462fc80e..801eecf1 100644
--- a/src/Store.ts
+++ b/src/Store.ts
@@ -40,8 +40,8 @@ const extract = <S, A>(wa: Store<S, A>): A => {
  *
  * @since 2.0.0
  */
-export function seek<S, A>(wa: Store<S, A>, s: S): Store<S, A> {
-  return { peek: wa.peek, pos: s }
+export function seek<S>(s: S): <A>(wa: Store<S, A>) => Store<S, A> {
+  return wa => ({ peek: wa.peek, pos: s })
 }
 
 /**
@@ -49,8 +49,8 @@ export function seek<S, A>(wa: Store<S, A>, s: S): Store<S, A> {
  *
  * @since 2.0.0
  */
-export function seeks<S, A>(wa: Store<S, A>, f: Endomorphism<S>): Store<S, A> {
-  return seek(wa, f(wa.pos))
+export function seeks<S>(f: Endomorphism<S>): <A>(wa: Store<S, A>) => Store<S, A> {
+  return wa => ({ peek: wa.peek, pos: f(wa.pos) })
 }
 
 /**
@@ -58,8 +58,8 @@ export function seeks<S, A>(wa: Store<S, A>, f: Endomorphism<S>): Store<S, A> {
  *
  * @since 2.0.0
  */
-export function peeks<S, A>(wa: Store<S, A>, f: Endomorphism<S>): A {
-  return wa.peek(f(wa.pos))
+export function peeks<S>(f: Endomorphism<S>): <A>(wa: Store<S, A>) => A {
+  return wa => wa.peek(f(wa.pos))
 }
 
 /**
@@ -69,23 +69,23 @@ export function peeks<S, A>(wa: Store<S, A>, f: Endomorphism<S>): A {
  */
 export function experiment<F extends URIS3>(
   F: Functor3<F>
-): <U, L, S, A>(wa: Store<S, A>, f: (s: S) => Type3<F, U, L, S>) => Type3<F, U, L, A>
+): <U, L, S>(f: (s: S) => Type3<F, U, L, S>) => <A>(wa: Store<S, A>) => Type3<F, U, L, A>
 export function experiment<F extends URIS2>(
   F: Functor2<F>
-): <L, S, A>(wa: Store<S, A>, f: (s: S) => Type2<F, L, S>) => Type2<F, L, A>
+): <L, S>(f: (s: S) => Type2<F, L, S>) => <A>(wa: Store<S, A>) => Type2<F, L, A>
 export function experiment<F extends URIS2, L>(
   F: Functor2C<F, L>
-): <S, A>(wa: Store<S, A>, f: (s: S) => Type2<F, L, S>) => Type2<F, L, A>
+): <S>(f: (s: S) => Type2<F, L, S>) => <A>(wa: Store<S, A>) => Type2<F, L, A>
 export function experiment<F extends URIS>(
   F: Functor1<F>
-): <S, A>(wa: Store<S, A>, f: (s: S) => Type<F, S>) => Type<F, A>
-export function experiment<F>(F: Functor<F>): <S, A>(wa: Store<S, A>, f: (s: S) => HKT<F, S>) => HKT<F, A>
-export function experiment<F>(F: Functor<F>): <S, A>(wa: Store<S, A>, f: (s: S) => HKT<F, S>) => HKT<F, A> {
-  return (sa, f) => F.map(f(sa.pos), s => sa.peek(s))
+): <S>(f: (s: S) => Type<F, S>) => <A>(wa: Store<S, A>) => Type<F, A>
+export function experiment<F>(F: Functor<F>): <S>(f: (s: S) => HKT<F, S>) => <A>(wa: Store<S, A>) => HKT<F, A>
+export function experiment<F>(F: Functor<F>): <S>(f: (s: S) => HKT<F, S>) => <A>(wa: Store<S, A>) => HKT<F, A> {
+  return f => wa => F.map(f(wa.pos), s => wa.peek(s))
 }
 
 const extend = <S, A, B>(wa: Store<S, A>, f: (wa: Store<S, A>) => B): Store<S, B> => {
-  return { peek: s => f(seek(wa, s)), pos: wa.pos }
+  return { peek: s => f({ peek: wa.peek, pos: s }), pos: wa.pos }
 }
 
 /**
diff --git a/src/TaskEither.ts b/src/TaskEither.ts
index c4f16864..25886f37 100644
--- a/src/TaskEither.ts
+++ b/src/TaskEither.ts
@@ -107,31 +107,38 @@ export function fromPredicate<L, A>(predicate: Predicate<A>, onFalse: (a: A) =>
 /**
  * @since 2.0.0
  */
-export const fold: <L, A, R>(ma: TaskEither<L, A>, onLeft: (l: L) => Task<R>, onRight: (a: A) => Task<R>) => Task<R> =
-  T.fold
+export const fold: <L, A, R>(
+  onLeft: (l: L) => Task<R>,
+  onRight: (a: A) => Task<R>
+) => (ma: TaskEither<L, A>) => Task<R> = T.fold
 
 /**
  * @since 2.0.0
  */
-export const getOrElse: <L, A>(ma: TaskEither<L, A>, f: (l: L) => Task<A>) => Task<A> = T.getOrElse
+export const getOrElse: <L, A>(f: (l: L) => Task<A>) => (ma: TaskEither<L, A>) => Task<A> = T.getOrElse
 
 /**
  * @since 2.0.0
  */
 export function filterOrElse<L, A, B extends A>(
-  ma: TaskEither<L, A>,
-  p: Refinement<A, B>,
+  predicate: Refinement<A, B>,
+  zero: (a: A) => L
+): (ma: TaskEither<L, A>) => TaskEither<L, B>
+export function filterOrElse<L, A>(
+  predicate: Predicate<A>,
+  zero: (a: A) => L
+): (ma: TaskEither<L, A>) => TaskEither<L, A>
+export function filterOrElse<L, A>(
+  predicate: Predicate<A>,
   zero: (a: A) => L
-): TaskEither<L, B>
-export function filterOrElse<L, A>(ma: TaskEither<L, A>, p: Predicate<A>, zero: (a: A) => L): TaskEither<L, A>
-export function filterOrElse<L, A>(ma: TaskEither<L, A>, p: Predicate<A>, zero: (a: A) => L): TaskEither<L, A> {
-  return task.map(ma, e => E.filterOrElse(e, p, zero))
+): (ma: TaskEither<L, A>) => TaskEither<L, A> {
+  return ma => task.map(ma, E.filterOrElse(predicate, zero))
 }
 
 /**
  * @since 2.0.0
  */
-export const orElse: <L, A, M>(ma: TaskEither<L, A>, f: (l: L) => TaskEither<M, A>) => TaskEither<M, A> = T.orElse
+export const orElse: <L, A, M>(f: (l: L) => TaskEither<M, A>) => (ma: TaskEither<L, A>) => TaskEither<M, A> = T.orElse
 
 /**
  * @since 2.0.0
@@ -248,7 +255,7 @@ export const taskEither: Monad2<URI> & Bifunctor2<URI> & Alt2<URI> & MonadIO2<UR
   of: right,
   ap: T.ap,
   chain: T.chain,
-  alt: orElse,
+  alt: T.alt,
   fromIO: rightIO,
   fromTask: rightTask
 }
diff --git a/src/These.ts b/src/These.ts
index a5af2fff..9136225a 100644
--- a/src/These.ts
+++ b/src/These.ts
@@ -26,7 +26,7 @@ import { Functor2 } from './Functor'
 import { HKT } from './HKT'
 import { Monad2C } from './Monad'
 import { Monoid } from './Monoid'
-import { Option, some, none, isNone, fold as foldOption } from './Option'
+import { Option, some, none, isNone } from './Option'
 import { Semigroup } from './Semigroup'
 import { fromEquals, Eq } from './Eq'
 import { Show } from './Show'
@@ -87,18 +87,19 @@ export function both<L, A>(left: L, right: A): These<L, A> {
  * @since 2.0.0
  */
 export function fold<L, A, R>(
-  fa: These<L, A>,
   onLeft: (l: L) => R,
   onRight: (a: A) => R,
   onBoth: (l: L, a: A) => R
-): R {
-  switch (fa._tag) {
-    case 'Left':
-      return onLeft(fa.left)
-    case 'Right':
-      return onRight(fa.right)
-    case 'Both':
-      return onBoth(fa.left, fa.right)
+): (fa: These<L, A>) => R {
+  return fa => {
+    switch (fa._tag) {
+      case 'Left':
+        return onLeft(fa.left)
+      case 'Right':
+        return onRight(fa.right)
+      case 'Both':
+        return onBoth(fa.left, fa.right)
+    }
   }
 }
 
@@ -107,8 +108,7 @@ export function fold<L, A, R>(
  */
 export function getShow<L, A>(SL: Show<L>, SA: Show<A>): Show<These<L, A>> {
   return {
-    show: fa =>
-      fold(fa, l => `left(${SL.show(l)})`, a => `right(${SA.show(a)})`, (l, a) => `both(${SL.show(l)}, ${SA.show(a)})`)
+    show: fold(l => `left(${SL.show(l)})`, a => `right(${SA.show(a)})`, (l, a) => `both(${SL.show(l)}, ${SA.show(a)})`)
   }
 }
 
@@ -213,14 +213,14 @@ const sequence = <F>(F: Applicative<F>) => <L, A>(ta: These<L, HKT<F, A>>): HKT<
  * @example
  * import { toTuple, left, right, both } from 'fp-ts/lib/These'
  *
- * assert.deepStrictEqual(toTuple(left('b'), 'a', 1), ['b', 1])
- * assert.deepStrictEqual(toTuple(right(2), 'a', 1), ['a', 2])
- * assert.deepStrictEqual(toTuple(both('b', 2), 'a', 1), ['b', 2])
+ * assert.deepStrictEqual(toTuple('a', 1)(left('b')), ['b', 1])
+ * assert.deepStrictEqual(toTuple('a', 1)(right(2)), ['a', 2])
+ * assert.deepStrictEqual(toTuple('a', 1)(both('b', 2)), ['b', 2])
  *
  * @since 2.0.0
  */
-export function toTuple<L, A>(fa: These<L, A>, l: L, a: A): [L, A] {
-  return isLeft(fa) ? [fa.left, a] : isRight(fa) ? [l, fa.right] : [fa.left, fa.right]
+export function toTuple<L, A>(l: L, a: A): (fa: These<L, A>) => [L, A] {
+  return fa => (isLeft(fa) ? [fa.left, a] : isRight(fa) ? [l, fa.right] : [fa.left, fa.right])
 }
 
 /**
@@ -362,11 +362,13 @@ export function getRightOnly<L, A>(fa: These<L, A>): Option<A> {
  * @since 2.0.0
  */
 export function fromOptions<L, A>(fl: Option<L>, fa: Option<A>): Option<These<L, A>> {
-  return foldOption(
-    fl,
-    () => foldOption(fa, () => none, a => some(right(a))),
-    l => foldOption(fa, () => some(left(l)), a => some(both(l, a)))
-  )
+  return isNone(fl)
+    ? isNone(fa)
+      ? none
+      : some(right(fa.value))
+    : isNone(fa)
+    ? some(left(fl.value))
+    : some(both(fl.value, fa.value))
 }
 
 /**
diff --git a/src/Traced.ts b/src/Traced.ts
index 0156fc7d..2dca475f 100644
--- a/src/Traced.ts
+++ b/src/Traced.ts
@@ -49,8 +49,8 @@ export function listen<P, A>(wa: Traced<P, A>): Traced<P, [A, P]> {
  *
  * @since 2.0.0
  */
-export function listens<P, A, B>(wa: Traced<P, A>, f: (p: P) => B): Traced<P, [A, B]> {
-  return e => tuple(wa(e), f(e))
+export function listens<P, B>(f: (p: P) => B): <A>(wa: Traced<P, A>) => Traced<P, [A, B]> {
+  return wa => e => tuple(wa(e), f(e))
 }
 
 /**
@@ -58,8 +58,8 @@ export function listens<P, A, B>(wa: Traced<P, A>, f: (p: P) => B): Traced<P, [A
  *
  * @since 2.0.0
  */
-export function censor<P, A>(wa: Traced<P, A>, f: (p: P) => P): Traced<P, A> {
-  return e => wa(f(e))
+export function censor<P>(f: (p: P) => P): <A>(wa: Traced<P, A>) => Traced<P, A> {
+  return wa => e => wa(f(e))
 }
 
 /**
diff --git a/src/Tree.ts b/src/Tree.ts
index 9e24190b..08b6ae05 100644
--- a/src/Tree.ts
+++ b/src/Tree.ts
@@ -182,7 +182,7 @@ const draw = (indentation: string, forest: Forest<string>): string => {
  *
  * @since 2.0.0
  */
-export const drawForest = (forest: Forest<string>): string => {
+export function drawForest(forest: Forest<string>): string {
   return draw('\n', forest)
 }
 
@@ -208,7 +208,7 @@ export const drawForest = (forest: Forest<string>): string => {
  *
  * @since 2.0.0
  */
-export const drawTree = (tree: Tree<string>): string => {
+export function drawTree(tree: Tree<string>): string {
   return tree.value + drawForest(tree.forest)
 }
 
@@ -217,7 +217,7 @@ export const drawTree = (tree: Tree<string>): string => {
  *
  * @since 2.0.0
  */
-export const unfoldTree = <A, B>(b: B, f: (b: B) => [A, Array<B>]): Tree<A> => {
+export function unfoldTree<A, B>(b: B, f: (b: B) => [A, Array<B>]): Tree<A> {
   const [a, bs] = f(b)
   return { value: a, forest: unfoldForest(bs, f) }
 }
@@ -227,7 +227,7 @@ export const unfoldTree = <A, B>(b: B, f: (b: B) => [A, Array<B>]): Tree<A> => {
  *
  * @since 2.0.0
  */
-export const unfoldForest = <A, B>(bs: Array<B>, f: (b: B) => [A, Array<B>]): Forest<A> => {
+export function unfoldForest<A, B>(bs: Array<B>, f: (b: B) => [A, Array<B>]): Forest<A> {
   return bs.map(b => unfoldTree(b, f))
 }
 
@@ -278,6 +278,7 @@ export function unfoldForestM<M>(
   M: Monad<M>
 ): <A, B>(bs: Array<B>, f: (b: B) => HKT<M, [A, Array<B>]>) => HKT<M, Forest<A>> {
   const traverseM = array.traverse(M)
+  // to avoid Maximum call stack size exceeded
   let unfoldTree: <A, B>(b: B, f: (b: B) => HKT<M, [A, Array<B>]>) => HKT<M, Tree<A>>
   return (bs, f) => {
     // tslint:disable-next-line
diff --git a/src/Writer.ts b/src/Writer.ts
index 2610f764..61c1f4d7 100644
--- a/src/Writer.ts
+++ b/src/Writer.ts
@@ -78,8 +78,8 @@ export function pass<W, A>(fa: Writer<W, [A, (w: W) => W]>): Writer<W, A> {
  *
  * @since 2.0.0
  */
-export function listens<W, A, B>(fa: Writer<W, A>, f: (w: W) => B): Writer<W, [A, B]> {
-  return () => {
+export function listens<W, B>(f: (w: W) => B): <A>(fa: Writer<W, A>) => Writer<W, [A, B]> {
+  return fa => () => {
     const [a, w] = fa()
     return [[a, f(w)], w]
   }
@@ -90,8 +90,8 @@ export function listens<W, A, B>(fa: Writer<W, A>, f: (w: W) => B): Writer<W, [A
  *
  * @since 2.0.0
  */
-export function censor<W, A>(fa: Writer<W, A>, f: (w: W) => W): Writer<W, A> {
-  return () => {
+export function censor<W>(f: (w: W) => W): <A>(fa: Writer<W, A>) => Writer<W, A> {
+  return fa => () => {
     const [a, w] = fa()
     return [a, f(w)]
   }
diff --git a/src/function.ts b/src/function.ts
index e4f6b561..431e6943 100644
--- a/src/function.ts
+++ b/src/function.ts
@@ -251,8 +251,8 @@ export function pipeOp<A, B, C, D, E, F, G, H, I, J>(
   hi: (h: H) => I,
   ij: (i: I) => J
 ): J
-export function pipeOp(a: any, ...fns: Array<Function>): any {
-  let r: any = a
+export function pipeOp(a: unknown, ...fns: Array<Function>): unknown {
+  let r: unknown = a
   for (let i = 0; i < fns.length; i++) {
     r = fns[i](r)
   }


Test patch:
diff --git a/test/Either.ts b/test/Either.ts
index 7e6edaa5..0292ac68 100644
--- a/test/Either.ts
+++ b/test/Either.ts
@@ -1,7 +1,7 @@
 import * as assert from 'assert'
 import * as _ from '../src/Either'
 import { eqNumber, eqString } from '../src/Eq'
-import { identity } from '../src/function'
+import { identity, pipeOp as pipe } from '../src/function'
 import * as I from '../src/Identity'
 import { monoidString, monoidSum } from '../src/Monoid'
 import { none, option, some } from '../src/Option'
@@ -12,30 +12,97 @@ describe('Either', () => {
   it('fold', () => {
     const f = (s: string) => `left${s.length}`
     const g = (s: string) => `right${s.length}`
-    assert.strictEqual(_.fold(_.left('abc'), f, g), 'left3')
-    assert.strictEqual(_.fold(_.right('abc'), f, g), 'right3')
+    const fold = _.fold(f, g)
+    assert.strictEqual(fold(_.left('abc')), 'left3')
+    assert.strictEqual(fold(_.right('abc')), 'right3')
   })
 
   it('getOrElse', () => {
-    assert.deepStrictEqual(_.getOrElse(_.right(12), () => 17), 12)
-    assert.deepStrictEqual(_.getOrElse(_.left('a'), () => 17), 17)
-    assert.deepStrictEqual(_.getOrElse(_.left('a'), (l: string) => l.length + 1), 2)
+    assert.deepStrictEqual(
+      pipe(
+        _.right(12),
+        _.getOrElse(() => 17)
+      ),
+      12
+    )
+    assert.deepStrictEqual(
+      pipe(
+        _.left('a'),
+        _.getOrElse(() => 17)
+      ),
+      17
+    )
+    assert.deepStrictEqual(
+      pipe(
+        _.left('a'),
+        _.getOrElse((l: string) => l.length + 1)
+      ),
+      2
+    )
+  })
+
+  it('elem', () => {
+    assert.deepStrictEqual(_.elem(eqNumber)(2, _.left('a')), false)
+    assert.deepStrictEqual(_.elem(eqNumber)(2, _.right(2)), true)
+    assert.deepStrictEqual(_.elem(eqNumber)(1, _.right(2)), false)
   })
 
   it('filterOrElse', () => {
     const gt10 = (n: number): boolean => n > 10
-    assert.deepStrictEqual(_.filterOrElse(_.right(12), gt10, () => -1), _.right(12))
-    assert.deepStrictEqual(_.filterOrElse(_.right(7), gt10, () => -1), _.left(-1))
-    assert.deepStrictEqual(_.filterOrElse(_.left(12), gt10, () => -1), _.left(12))
-    assert.deepStrictEqual(_.filterOrElse(_.right(7), gt10, n => `invalid ${n}`), _.left('invalid 7'))
+    assert.deepStrictEqual(
+      pipe(
+        _.right(12),
+        _.filterOrElse(gt10, () => -1)
+      ),
+      _.right(12)
+    )
+    assert.deepStrictEqual(
+      pipe(
+        _.right(7),
+        _.filterOrElse(gt10, () => -1)
+      ),
+      _.left(-1)
+    )
+    assert.deepStrictEqual(
+      pipe(
+        _.left(12),
+        _.filterOrElse(gt10, () => -1)
+      ),
+      _.left(12)
+    )
+    assert.deepStrictEqual(
+      pipe(
+        _.right(7),
+        _.filterOrElse(gt10, n => `invalid ${n}`)
+      ),
+      _.left('invalid 7')
+    )
 
     type Color = 'red' | 'blue'
     const isColor = (s: string): s is Color => s === 'red' || s === 'blue'
     const errorHandler = (s: string) => `invalid color ${s}`
 
-    assert.deepStrictEqual(_.filterOrElse(_.right('red'), isColor, errorHandler), _.right('red'))
-    assert.deepStrictEqual(_.filterOrElse(_.right('foo'), isColor, errorHandler), _.left('invalid color foo'))
-    assert.deepStrictEqual(_.filterOrElse(_.left('err'), isColor, errorHandler), _.left('err'))
+    assert.deepStrictEqual(
+      pipe(
+        _.right('red'),
+        _.filterOrElse(isColor, errorHandler)
+      ),
+      _.right('red')
+    )
+    assert.deepStrictEqual(
+      pipe(
+        _.right('foo'),
+        _.filterOrElse(isColor, errorHandler)
+      ),
+      _.left('invalid color foo')
+    )
+    assert.deepStrictEqual(
+      pipe(
+        _.left('err'),
+        _.filterOrElse(isColor, errorHandler)
+      ),
+      _.left('err')
+    )
   })
 
   it('isLeft', () => {
@@ -49,10 +116,41 @@ describe('Either', () => {
   })
 
   it('orElse', () => {
-    assert.deepStrictEqual(_.orElse(_.right(1), () => _.right(2)), _.right(1))
-    assert.deepStrictEqual(_.orElse(_.right(1), () => _.left('foo')), _.right(1))
-    assert.deepStrictEqual(_.orElse(_.left('foo'), () => _.right(1)), _.right(1))
-    assert.deepStrictEqual(_.orElse(_.left('foo'), () => _.left('bar')), _.left('bar'))
+    assert.deepStrictEqual(
+      pipe(
+        _.right(1),
+        _.orElse(() => _.right(2))
+      ),
+      _.right(1)
+    )
+    assert.deepStrictEqual(
+      pipe(
+        _.right(1),
+        _.orElse(() => _.left('foo') as _.Either<string, number>)
+      ),
+      _.right(1)
+    )
+    assert.deepStrictEqual(
+      pipe(
+        _.left('a'),
+        _.orElse(() => _.right(1))
+      ),
+      _.right(1)
+    )
+    assert.deepStrictEqual(
+      pipe(
+        _.left('a'),
+        _.orElse(() => _.left('b'))
+      ),
+      _.left('b')
+    )
+  })
+
+  it('alt', () => {
+    assert.deepStrictEqual(_.either.alt(_.right(1), () => _.right(2)), _.right(1))
+    assert.deepStrictEqual(_.either.alt(_.right(1), () => _.left('a')), _.right(1))
+    assert.deepStrictEqual(_.either.alt(_.left('a'), () => _.right(2)), _.right(2))
+    assert.deepStrictEqual(_.either.alt(_.left('a'), () => _.left('b')), _.left('b'))
   })
 
   it('swap', () => {
diff --git a/test/EitherT.ts b/test/EitherT.ts
index 49067207..660a6b07 100644
--- a/test/EitherT.ts
+++ b/test/EitherT.ts
@@ -2,6 +2,7 @@ import * as assert from 'assert'
 import * as E from '../src/Either'
 import { getEitherM } from '../src/EitherT'
 import { io } from '../src/IO'
+import { pipeOp as pipe } from '../src/function'
 
 const T = getEitherM(io)
 
@@ -9,13 +10,26 @@ describe('EitherT', () => {
   it('fold', () => {
     const onLeft = (s: string) => io.of(`left(${s})`)
     const onRight = (n: number) => io.of(`right(${n})`)
-    assert.strictEqual(T.fold(io.of(E.right(1)), onLeft, onRight)(), 'right(1)')
-    assert.strictEqual(T.fold(io.of(E.left('bb')), onLeft, onRight)(), 'left(bb)')
+    const fold = T.fold(onLeft, onRight)
+    assert.strictEqual(fold(io.of(E.right(1)))(), 'right(1)')
+    assert.strictEqual(fold(io.of(E.left('bb')))(), 'left(bb)')
   })
 
   it('getOrElse', () => {
     const onLeft = (s: string) => io.of(`left(${s})`)
-    assert.strictEqual(T.getOrElse(io.of<E.Either<string, string>>(E.right('a')), onLeft)(), 'a')
-    assert.strictEqual(T.getOrElse(io.of(E.left('bb')), onLeft)(), 'left(bb)')
+    assert.strictEqual(
+      pipe(
+        io.of(E.right('a')),
+        T.getOrElse(onLeft)
+      )(),
+      'a'
+    )
+    assert.strictEqual(
+      pipe(
+        io.of(E.left('bb')),
+        T.getOrElse(onLeft)
+      )(),
+      'left(bb)'
+    )
   })
 })
diff --git a/test/IOEither.ts b/test/IOEither.ts
index f600c7fc..8bc2096d 100644
--- a/test/IOEither.ts
+++ b/test/IOEither.ts
@@ -5,6 +5,7 @@ import * as _ from '../src/IOEither'
 import { monoidString } from '../src/Monoid'
 import { semigroupSum } from '../src/Semigroup'
 import { none, some } from '../src/Option'
+import { pipeOp as pipe } from '../src/function'
 
 describe('IOEither', () => {
   it('tryCatch', () => {
@@ -20,11 +21,41 @@ describe('IOEither', () => {
   it('filterOrElse', () => {
     const isNumber = (u: string | number): u is number => typeof u === 'number'
 
-    assert.deepStrictEqual(_.filterOrElse(_.right(12), n => n > 10, () => 'bar')(), E.right(12))
-    assert.deepStrictEqual(_.filterOrElse(_.right(7), n => n > 10, () => 'bar')(), E.left('bar'))
-    assert.deepStrictEqual(_.filterOrElse(_.left('foo'), n => n > 10, () => 'bar')(), E.left('foo'))
-    assert.deepStrictEqual(_.filterOrElse(_.right(7), n => n > 10, n => `invalid ${n}`)(), E.left('invalid 7'))
-    assert.deepStrictEqual(_.filterOrElse(_.right(12), isNumber, () => 'not a number')(), E.right(12))
+    assert.deepStrictEqual(
+      pipe(
+        _.right(12),
+        _.filterOrElse(n => n > 10, () => 'bar')
+      )(),
+      E.right(12)
+    )
+    assert.deepStrictEqual(
+      pipe(
+        _.right(7),
+        _.filterOrElse(n => n > 10, () => 'bar')
+      )(),
+      E.left('bar')
+    )
+    assert.deepStrictEqual(
+      pipe(
+        _.left('foo'),
+        _.filterOrElse(n => n > 10, () => 'bar')
+      )(),
+      E.left('foo')
+    )
+    assert.deepStrictEqual(
+      pipe(
+        _.right(7),
+        _.filterOrElse(n => n > 10, n => `invalid ${n}`)
+      )(),
+      E.left('invalid 7')
+    )
+    assert.deepStrictEqual(
+      pipe(
+        _.right(12),
+        _.filterOrElse(isNumber, () => 'not a number')
+      )(),
+      E.right(12)
+    )
   })
 
   it('fromOption', () => {
diff --git a/test/Option.ts b/test/Option.ts
index 29f44954..8a2b72b2 100644
--- a/test/Option.ts
+++ b/test/Option.ts
@@ -1,13 +1,13 @@
 import * as assert from 'assert'
 import { array } from '../src/Array'
 import { left, right } from '../src/Either'
+import { eqNumber } from '../src/Eq'
+import { identity, pipeOp as pipe } from '../src/function'
+import * as I from '../src/Identity'
+import { monoidString, monoidSum } from '../src/Monoid'
 import * as O from '../src/Option'
 import { ordString } from '../src/Ord'
 import { semigroupString, semigroupSum } from '../src/Semigroup'
-import { eqNumber } from '../src/Eq'
-import { identity } from '../src/function'
-import * as I from '../src/Identity'
-import { monoidSum, monoidString } from '../src/Monoid'
 import { showString } from '../src/Show'
 
 const p = (n: number): boolean => n > 2
@@ -20,8 +20,9 @@ describe('Option', () => {
   it('fold', () => {
     const f = () => 'none'
     const g = (s: string) => `some${s.length}`
-    assert.strictEqual(O.fold(O.none, f, g), 'none')
-    assert.strictEqual(O.fold(O.some('abc'), f, g), 'some3')
+    const fold = O.fold(f, g)
+    assert.strictEqual(fold(O.none), 'none')
+    assert.strictEqual(fold(O.some('abc')), 'some3')
   })
 
   it('toNullable', () => {
@@ -35,8 +36,20 @@ describe('Option', () => {
   })
 
   it('getOrElse', () => {
-    assert.strictEqual(O.getOrElse(O.some(1), () => 0), 1)
-    assert.strictEqual(O.getOrElse(O.none, () => 0), 0)
+    assert.strictEqual(
+      pipe(
+        O.some(1),
+        O.getOrElse(() => 0)
+      ),
+      1
+    )
+    assert.strictEqual(
+      pipe(
+        O.none,
+        O.getOrElse(() => 0)
+      ),
+      0
+    )
   })
 
   it('equals', () => {
@@ -75,20 +88,45 @@ describe('Option', () => {
   })
 
   it('mapNullable', () => {
-    type Nested = {
-      foo?: number
-      foo2: {
-        bar2?: string
+    interface X {
+      a?: {
+        b?: {
+          c?: {
+            d: number
+          }
+        }
       }
     }
-    const nested: Nested = {
-      foo2: {}
-    }
-    const nestedOption = O.some(nested)
-    assert.deepStrictEqual(O.mapNullable(nestedOption, value => value.foo), O.none)
-    assert.deepStrictEqual(O.mapNullable(nestedOption, value => value.foo2), O.some(nested.foo2))
-    assert.deepStrictEqual(O.mapNullable(nestedOption, value => value.foo2.bar2), O.none)
-    assert.deepStrictEqual(O.mapNullable(O.none, identity), O.none)
+    const x1: X = { a: {} }
+    const x2: X = { a: { b: {} } }
+    const x3: X = { a: { b: { c: { d: 1 } } } }
+    assert.deepStrictEqual(
+      pipe(
+        O.fromNullable(x1.a),
+        O.mapNullable(x => x.b),
+        O.mapNullable(x => x.c),
+        O.mapNullable(x => x.d)
+      ),
+      O.none
+    )
+    assert.deepStrictEqual(
+      pipe(
+        O.fromNullable(x2.a),
+        O.mapNullable(x => x.b),
+        O.mapNullable(x => x.c),
+        O.mapNullable(x => x.d)
+      ),
+      O.none
+    )
+    assert.deepStrictEqual(
+      pipe(
+        O.fromNullable(x3.a),
+        O.mapNullable(x => x.b),
+        O.mapNullable(x => x.c),
+        O.mapNullable(x => x.d)
+      ),
+      O.some(1)
+    )
   })
 
   it('ap', () => {
@@ -125,7 +163,7 @@ describe('Option', () => {
   })
 
   it('extend', () => {
-    const f = (fa: O.Option<number>) => O.getOrElse(fa, () => 0)
+    const f = O.getOrElse(() => 0)
     assert.deepStrictEqual(O.option.extend(O.some(2), f), O.some(2))
     assert.deepStrictEqual(O.option.extend(O.none, f), O.none)
   })
@@ -215,10 +253,9 @@ describe('Option', () => {
   })
 
   it('elem', () => {
-    const elem = O.elem(eqNumber)
-    assert.deepStrictEqual(elem(2, O.none), false)
-    assert.deepStrictEqual(elem(2, O.some(2)), true)
-    assert.deepStrictEqual(elem(1, O.some(2)), false)
+    assert.deepStrictEqual(O.elem(eqNumber)(2, O.none), false)
+    assert.deepStrictEqual(O.elem(eqNumber)(2, O.some(2)), true)
+    assert.deepStrictEqual(O.elem(eqNumber)(1, O.some(2)), false)
   })
 
   it('isNone', () => {
@@ -233,9 +270,27 @@ describe('Option', () => {
 
   it('exists', () => {
     const predicate = (a: number) => a === 2
-    assert.deepStrictEqual(O.exists(O.none, predicate), false)
-    assert.deepStrictEqual(O.exists(O.some(1), predicate), false)
-    assert.deepStrictEqual(O.exists(O.some(2), predicate), true)
+    assert.deepStrictEqual(
+      pipe(
+        O.none,
+        O.exists(predicate)
+      ),
+      false
+    )
+    assert.deepStrictEqual(
+      pipe(
+        O.some(1),
+        O.exists(predicate)
+      ),
+      false
+    )
+    assert.deepStrictEqual(
+      pipe(
+        O.some(2),
+        O.exists(predicate)
+      ),
+      true
+    )
   })
 
   it('tryCatch', () => {
diff --git a/test/OptionT.ts b/test/OptionT.ts
index 2f28f17d..dd1d72e9 100644
--- a/test/OptionT.ts
+++ b/test/OptionT.ts
@@ -2,6 +2,7 @@ import * as assert from 'assert'
 import * as O from '../src/Option'
 import { getOptionM } from '../src/OptionT'
 import { task } from '../src/Task'
+import { pipeOp as pipe } from '../src/function'
 
 const T = getOptionM(task)
 
@@ -26,16 +27,30 @@ describe('OptionT', () => {
   it('fold', async () => {
     const f = () => task.of('none')
     const g = (s: string) => task.of(`some${s.length}`)
-    const s1 = await T.fold(task.of(O.none), f, g)()
+    const fold = T.fold(f, g)
+    const s1 = await fold(task.of(O.none))()
     assert.strictEqual(s1, 'none')
-    const s2 = await T.fold(T.of('s'), f, g)()
+    const s2 = await fold(T.of('s'))()
     assert.strictEqual(s2, 'some1')
   })
 
+  it('alt', async () => {
+    const o1 = await T.alt(task.of(O.some(1)), () => task.of(O.some(2)))()
+    assert.deepStrictEqual(o1, O.some(1))
+    const o2 = await T.alt(task.of(O.none), () => task.of(O.some(2)))()
+    assert.deepStrictEqual(o2, O.some(2))
+  })
+
   it('getOrElse', async () => {
-    const n1 = await T.getOrElse(task.of(O.some(1)), () => task.of(2))()
-    const n2 = await T.getOrElse(task.of(O.none), () => task.of(2))()
+    const n1 = await pipe(
+      task.of(O.some(1)),
+      T.getOrElse(() => task.of(2))
+    )()
     assert.strictEqual(n1, 1)
+    const n2 = await pipe(
+      task.of(O.none),
+      T.getOrElse(() => task.of(2))
+    )()
     assert.strictEqual(n2, 2)
   })
 
diff --git a/test/Reader.ts b/test/Reader.ts
index 57823f61..5da29921 100644
--- a/test/Reader.ts
+++ b/test/Reader.ts
@@ -2,6 +2,7 @@ import * as assert from 'assert'
 import * as R from '../src/Reader'
 import { semigroupSum } from '../src/Semigroup'
 import { monoidSum } from '../src/Monoid'
+import { pipeOp as pipe } from '../src/function'
 
 interface Env {
   count: number
@@ -31,11 +32,13 @@ describe('Reader', () => {
   })
 
   it('local', () => {
-    type E = string
-    interface E2 {
+    interface E {
       name: string
     }
-    const x = R.local((e: E) => e.length, (e2: E2) => e2.name)
+    const x = pipe(
+      (s: string) => s.length,
+      R.local((e: E) => e.name)
+    )
     assert.strictEqual(x({ name: 'foo' }), 3)
   })
 
diff --git a/test/ReaderTaskEither.ts b/test/ReaderTaskEither.ts
index 7ed74651..d8b2ba2d 100644
--- a/test/ReaderTaskEither.ts
+++ b/test/ReaderTaskEither.ts
@@ -6,6 +6,7 @@ import { reader } from '../src/Reader'
 import * as _ from '../src/ReaderTaskEither'
 import { task } from '../src/Task'
 import { taskEither } from '../src/TaskEither'
+import { pipeOp as pipe } from '../src/function'
 
 describe('ReaderTaskEither', () => {
   describe('Monad', () => {
@@ -64,9 +65,14 @@ describe('ReaderTaskEither', () => {
 
   it('local', async () => {
     const len = (s: string): number => s.length
-    const rte = _.local(_.asks((n: number) => n + 1), len)
-    const e_1 = await _.run(rte, 'foo')
-    assert.deepStrictEqual(e_1, E.right(4))
+    const e = await _.run(
+      pipe(
+        _.asks((n: number) => n + 1),
+        _.local(len)
+      ),
+      'aaa'
+    )
+    assert.deepStrictEqual(e, E.right(4))
   })
 
   it('leftTask', async () => {
@@ -107,30 +113,54 @@ describe('ReaderTaskEither', () => {
   })
 
   it('fold', async () => {
-    const e1 = await _.fold(_.right(1), (l: string) => reader.of(task.of(l.length)), a => reader.of(task.of(a * 2)))(
-      {}
-    )()
+    const fold = _.fold((l: string) => reader.of(task.of(l.length)), (a: number) => reader.of(task.of(a * 2)))
+    const e1 = await fold(_.right(1))({})()
     assert.deepStrictEqual(e1, 2)
-    const e2 = await _.fold(_.left('err'), (l: string) => reader.of(task.of(l.length)), a => reader.of(task.of(a * 2)))(
-      {}
-    )()
+    const e2 = await fold(_.left('err'))({})()
     assert.deepStrictEqual(e2, 3)
   })
 
   it('getOrElse', async () => {
-    const e1 = await _.getOrElse(_.right(1), (l: string) => reader.of(task.of(l.length)))({})()
+    const e1 = await pipe(
+      _.right(1),
+      _.getOrElse((l: string) => reader.of(task.of(l.length)))
+    )({})()
     assert.deepStrictEqual(e1, 1)
-    const e2 = await _.getOrElse(_.left('err'), (l: string) => reader.of(task.of(l.length)))({})()
+    const e2 = await pipe(
+      _.left('err'),
+      _.getOrElse((l: string) => reader.of(task.of(l.length)))
+    )({})()
     assert.deepStrictEqual(e2, 3)
   })
 
   it('orElse', async () => {
-    const e1 = await _.run(_.orElse(_.right(1), (s: string) => _.right(s.length)), {})
+    const e1 = await _.run(
+      pipe(
+        _.right(1),
+        _.orElse((s: string) => _.right(s.length))
+      ),
+      {}
+    )
     assert.deepStrictEqual(e1, E.right(1))
-    const e2 = await _.run(_.orElse(_.left('error'), s => _.right(s.length)), {})
+    const e2 = await _.run(
+      pipe(
+        _.left('error'),
+        _.orElse(s => _.right(s.length))
+      ),
+      {}
+    )
     assert.deepStrictEqual(e2, E.right(5))
   })
 
+  it('alt', async () => {
+    const e1 = await _.run(_.readerTaskEither.alt(_.right(1), () => _.right(2)), {})
+    assert.deepStrictEqual(e1, E.right(1))
+    const e2 = await _.run(_.readerTaskEither.alt(_.left('a'), () => _.right(2)), {})
+    assert.deepStrictEqual(e2, E.right(2))
+    const e3 = await _.run(_.readerTaskEither.alt(_.left('a'), () => _.left('b')), {})
+    assert.deepStrictEqual(e3, E.left('b'))
+  })
+
   it('fromPredicate', () => {
     const predicate = (n: number) => n >= 2
     const gt2 = _.fromPredicate(predicate, n => `Invalid number ${n}`)
diff --git a/test/Record.ts b/test/Record.ts
index 23bb4f82..55447b11 100644
--- a/test/Record.ts
+++ b/test/Record.ts
@@ -104,7 +104,7 @@ describe('Record', () => {
     const t1 = R.traverseWithIndex(option)(d1, (k, n): Option<number> => (k !== 'k1' ? some(n) : none))
     assert.deepStrictEqual(t1, none)
     const t2 = R.traverseWithIndex(option)(R.empty, (): Option<number> => none)
-    assert.strictEqual(getOrElse(t2, () => R.empty), R.empty)
+    assert.strictEqual(getOrElse((): Record<string, number> => R.empty)(t2), R.empty)
   })
 
   it('size', () => {
diff --git a/test/Store.ts b/test/Store.ts
index 9e32a26a..71bf6f3c 100644
--- a/test/Store.ts
+++ b/test/Store.ts
@@ -1,6 +1,7 @@
 import * as assert from 'assert'
 import { Store, store, seek, seeks, peeks, experiment } from '../src/Store'
 import { array } from '../src/Array'
+import { pipeOp as pipe } from '../src/function'
 
 const len = (s: string): number => s.length
 
@@ -17,21 +18,49 @@ describe('Store', () => {
 
   it('seek', () => {
     const wa: Store<string, number> = { peek: len, pos: 'a' }
-    assert.strictEqual(store.extract(seek(wa, 'aa')), 2)
+    assert.strictEqual(
+      store.extract(
+        pipe(
+          wa,
+          seek('aa')
+        )
+      ),
+      2
+    )
   })
 
   it('seeks', () => {
     const wa: Store<string, number> = { peek: len, pos: 'a' }
-    assert.strictEqual(store.extract(seeks(wa, s => s + 'a')), 2)
+    assert.strictEqual(
+      store.extract(
+        pipe(
+          wa,
+          seeks(s => s + 'a')
+        )
+      ),
+      2
+    )
   })
 
   it('peeks', () => {
     const wa: Store<string, number> = { peek: len, pos: 'a' }
-    assert.strictEqual(peeks(wa, s => s + 'a'), 2)
+    assert.strictEqual(
+      pipe(
+        wa,
+        peeks(s => s + 'a')
+      ),
+      2
+    )
   })
 
   it('experiment', () => {
     const wa: Store<string, number> = { peek: len, pos: 'a' }
-    assert.deepStrictEqual(experiment(array)(wa, s => [s, s + 'a']), [1, 2])
+    assert.deepStrictEqual(
+      pipe(
+        wa,
+        experiment(array)(s => [s, s + 'a'])
+      ),
+      [1, 2]
+    )
   })
 })
diff --git a/test/TaskEither.ts b/test/TaskEither.ts
index f67f654b..3650d501 100644
--- a/test/TaskEither.ts
+++ b/test/TaskEither.ts
@@ -6,6 +6,7 @@ import { monoidString } from '../src/Monoid'
 import { semigroupSum } from '../src/Semigroup'
 import * as T from '../src/Task'
 import * as _ from '../src/TaskEither'
+import { pipeOp as pipe } from '../src/function'
 
 const delay = <A>(millis: number, a: A): T.Task<A> => T.delay(millis, T.task.of(a))
 
@@ -105,9 +106,15 @@ describe('TaskEither', () => {
   })
 
   it('orElse', async () => {
-    const e1 = await _.orElse(_.left('foo'), l => _.right(l.length))()
-    const e2 = await _.orElse(_.right(1), () => _.right(2))()
+    const e1 = await pipe(
+      _.left('foo'),
+      _.orElse(l => _.right(l.length))
+    )()
     assert.deepStrictEqual(e1, E.right(3))
+    const e2 = await pipe(
+      _.right(1),
+      _.orElse(() => _.right(2))
+    )()
     assert.deepStrictEqual(e2, E.right(1))
   })
 
@@ -241,15 +248,30 @@ describe('TaskEither', () => {
   it('filterOrElse', async () => {
     const isNumber = (u: string | number): u is number => typeof u === 'number'
 
-    const e1 = await _.filterOrElse(_.right(12), n => n > 10, () => 'bar')()
+    const e1 = await pipe(
+      _.right(12),
+      _.filterOrElse(n => n > 10, () => 'bar')
+    )()
     assert.deepStrictEqual(e1, E.right(12))
-    const e2 = await _.filterOrElse(_.right(7), n => n > 10, () => 'bar')()
+    const e2 = await pipe(
+      _.right(7),
+      _.filterOrElse(n => n > 10, () => 'bar')
+    )()
     assert.deepStrictEqual(e2, E.left('bar'))
-    const e3 = await _.filterOrElse(_.left('foo'), n => n > 10, () => 'bar')()
+    const e3 = await pipe(
+      _.left('foo'),
+      _.filterOrElse(n => n > 10, () => 'bar')
+    )()
     assert.deepStrictEqual(e3, E.left('foo'))
-    const e4 = await _.filterOrElse(_.right(7), n => n > 10, n => `invalid ${n}`)()
+    const e4 = await pipe(
+      _.right(7),
+      _.filterOrElse(n => n > 10, n => `invalid ${n}`)
+    )()
     assert.deepStrictEqual(e4, E.left('invalid 7'))
-    const e5 = await _.filterOrElse(_.right(12), isNumber, () => 'not a number')()
+    const e5 = await pipe(
+      _.right(12),
+      _.filterOrElse(isNumber, () => 'not a number')
+    )()
     assert.deepStrictEqual(e5, E.right(12))
   })
 
diff --git a/test/These.ts b/test/These.ts
index f129fd83..045ff87e 100644
--- a/test/These.ts
+++ b/test/These.ts
@@ -1,72 +1,51 @@
 import * as assert from 'assert'
-import { identity } from '../src/function'
+import { identity, pipeOp as pipe } from '../src/function'
 import { monoidString, monoidSum } from '../src/Monoid'
 import { none, option, some } from '../src/Option'
 import { semigroupString } from '../src/Semigroup'
 import { eqNumber } from '../src/Eq'
 import { showString } from '../src/Show'
-import {
-  both,
-  fold,
-  fromOptions,
-  getLeft,
-  getLeftOnly,
-  getMonad,
-  getRight,
-  getRightOnly,
-  getSemigroup,
-  getEq,
-  getShow,
-  isBoth,
-  isLeft,
-  isRight,
-  left,
-  leftOrBoth,
-  right,
-  rightOrBoth,
-  these,
-  toTuple
-} from '../src/These'
+import * as _ from '../src/These'
 
 describe('These', () => {
   it('getEq', () => {
-    const { equals } = getEq(eqNumber, eqNumber)
-    assert.strictEqual(equals(left(2), left(2)), true)
-    assert.strictEqual(equals(left(2), left(3)), false)
-    assert.strictEqual(equals(left(3), left(2)), false)
-    assert.strictEqual(equals(left(2), right(2)), false)
-    assert.strictEqual(equals(left(2), both(2, 2)), false)
-    assert.strictEqual(equals(right(2), right(2)), true)
-    assert.strictEqual(equals(right(2), right(3)), false)
-    assert.strictEqual(equals(right(3), right(2)), false)
-    assert.strictEqual(equals(right(2), both(2, 2)), false)
-    assert.strictEqual(equals(both(2, 2), both(2, 2)), true)
-    assert.strictEqual(equals(both(2, 3), both(3, 2)), false)
+    const { equals } = _.getEq(eqNumber, eqNumber)
+    assert.strictEqual(equals(_.left(2), _.left(2)), true)
+    assert.strictEqual(equals(_.left(2), _.left(3)), false)
+    assert.strictEqual(equals(_.left(3), _.left(2)), false)
+    assert.strictEqual(equals(_.left(2), _.right(2)), false)
+    assert.strictEqual(equals(_.left(2), _.both(2, 2)), false)
+    assert.strictEqual(equals(_.right(2), _.right(2)), true)
+    assert.strictEqual(equals(_.right(2), _.right(3)), false)
+    assert.strictEqual(equals(_.right(3), _.right(2)), false)
+    assert.strictEqual(equals(_.right(2), _.both(2, 2)), false)
+    assert.strictEqual(equals(_.both(2, 2), _.both(2, 2)), true)
+    assert.strictEqual(equals(_.both(2, 3), _.both(3, 2)), false)
   })
 
   it('getSemigroup', () => {
-    const { concat } = getSemigroup(monoidString, monoidSum)
-    assert.deepStrictEqual(concat(left('a'), left('b')), left('ab'))
-    assert.deepStrictEqual(concat(left('a'), right(2)), both('a', 2))
-    assert.deepStrictEqual(concat(right(2), left('a')), both('a', 2))
-    assert.deepStrictEqual(concat(left('a'), both('b', 2)), both('ab', 2))
-    assert.deepStrictEqual(concat(both('b', 2), left('a')), both('ba', 2))
-    assert.deepStrictEqual(concat(right(3), right(2)), right(5))
-    assert.deepStrictEqual(concat(right(3), both('b', 2)), both('b', 5))
-    assert.deepStrictEqual(concat(both('b', 2), right(3)), both('b', 5))
-    assert.deepStrictEqual(concat(both('a', 3), both('b', 2)), both('ab', 5))
+    const { concat } = _.getSemigroup(monoidString, monoidSum)
+    assert.deepStrictEqual(concat(_.left('a'), _.left('b')), _.left('ab'))
+    assert.deepStrictEqual(concat(_.left('a'), _.right(2)), _.both('a', 2))
+    assert.deepStrictEqual(concat(_.right(2), _.left('a')), _.both('a', 2))
+    assert.deepStrictEqual(concat(_.left('a'), _.both('b', 2)), _.both('ab', 2))
+    assert.deepStrictEqual(concat(_.both('b', 2), _.left('a')), _.both('ba', 2))
+    assert.deepStrictEqual(concat(_.right(3), _.right(2)), _.right(5))
+    assert.deepStrictEqual(concat(_.right(3), _.both('b', 2)), _.both('b', 5))
+    assert.deepStrictEqual(concat(_.both('b', 2), _.right(3)), _.both('b', 5))
+    assert.deepStrictEqual(concat(_.both('a', 3), _.both('b', 2)), _.both('ab', 5))
   })
 
   it('map', () => {
     const double = (n: number) => n * 2
-    assert.deepStrictEqual(these.map(left(2), double), left(2))
-    assert.deepStrictEqual(these.map(right(2), double), right(4))
-    assert.deepStrictEqual(these.map(both(1, 2), double), both(1, 4))
+    assert.deepStrictEqual(_.these.map(_.left(2), double), _.left(2))
+    assert.deepStrictEqual(_.these.map(_.right(2), double), _.right(4))
+    assert.deepStrictEqual(_.these.map(_.both(1, 2), double), _.both(1, 4))
   })
 
   it('getMonad', () => {
     const double = (n: number) => n * 2
-    const F = getMonad(semigroupString)
+    const F = _.getMonad(semigroupString)
     const fab = F.of(double)
     const fa = F.of(1)
     assert.deepStrictEqual(F.ap(fab, fa), F.of(2))
@@ -76,160 +55,182 @@ describe('These', () => {
     const double = (n: number) => n * 2
     const len = (s: string) => s.length
     const f = (s: string, n: number) => len(s) + double(n)
-    assert.strictEqual(fold(left('foo'), len, double, f), 3)
-    assert.strictEqual(fold(right(1), len, double, f), 2)
-    assert.strictEqual(fold(both('foo', 1), len, double, f), 5)
+    const fold = _.fold(len, double, f)
+    assert.strictEqual(fold(_.left('foo')), 3)
+    assert.strictEqual(fold(_.right(1)), 2)
+    assert.strictEqual(fold(_.both('foo', 1)), 5)
   })
 
   describe('Bifunctor', () => {
     it('bimap', () => {
       const len = (s: string): number => s.length
       const double = (n: number): number => n * 2
-      assert.deepStrictEqual(these.bimap(left('a'), len, double), left(1))
-      assert.deepStrictEqual(these.bimap(right(2), len, double), right(4))
-      assert.deepStrictEqual(these.bimap(both('foo', 1), len, double), both(3, 2))
+      assert.deepStrictEqual(_.these.bimap(_.left('a'), len, double), _.left(1))
+      assert.deepStrictEqual(_.these.bimap(_.right(2), len, double), _.right(4))
+      assert.deepStrictEqual(_.these.bimap(_.both('foo', 1), len, double), _.both(3, 2))
     })
 
     it('mapLeft', () => {
       const len = (s: string): number => s.length
-      assert.deepStrictEqual(these.mapLeft(left('a'), len), left(1))
-      assert.deepStrictEqual(these.mapLeft(right(2), len), right(2))
-      assert.deepStrictEqual(these.mapLeft(both('foo', 1), len), both(3, 1))
+      assert.deepStrictEqual(_.these.mapLeft(_.left('a'), len), _.left(1))
+      assert.deepStrictEqual(_.these.mapLeft(_.right(2), len), _.right(2))
+      assert.deepStrictEqual(_.these.mapLeft(_.both('foo', 1), len), _.both(3, 1))
     })
   })
 
   it('toTuple', () => {
-    assert.deepStrictEqual(toTuple(left('b'), 'a', 1), ['b', 1])
-    assert.deepStrictEqual(toTuple(right(2), 'a', 1), ['a', 2])
-    assert.deepStrictEqual(toTuple(both('b', 2), 'a', 1), ['b', 2])
+    assert.deepStrictEqual(
+      pipe(
+        _.left('b'),
+        _.toTuple('a', 1)
+      ),
+      ['b', 1]
+    )
+    assert.deepStrictEqual(
+      pipe(
+        _.right(2),
+        _.toTuple('a', 1)
+      ),
+      ['a', 2]
+    )
+    assert.deepStrictEqual(
+      pipe(
+        _.both('b', 2),
+        _.toTuple('a', 1)
+      ),
+      ['b', 2]
+    )
   })
 
   it('traverse', () => {
-    assert.deepStrictEqual(these.traverse(option)(left('a'), n => (n >= 2 ? some(n) : none)), some(left('a')))
-    assert.deepStrictEqual(these.traverse(option)(right(2), n => (n >= 2 ? some(n) : none)), some(right(2)))
-    assert.deepStrictEqual(these.traverse(option)(right(1), n => (n >= 2 ? some(n) : none)), none)
-    assert.deepStrictEqual(these.traverse(option)(both('a', 2), n => (n >= 2 ? some(n) : none)), some(both('a', 2)))
-    assert.deepStrictEqual(these.traverse(option)(both('a', 1), n => (n >= 2 ? some(n) : none)), none)
+    assert.deepStrictEqual(_.these.traverse(option)(_.left('a'), n => (n >= 2 ? some(n) : none)), some(_.left('a')))
+    assert.deepStrictEqual(_.these.traverse(option)(_.right(2), n => (n >= 2 ? some(n) : none)), some(_.right(2)))
+    assert.deepStrictEqual(_.these.traverse(option)(_.right(1), n => (n >= 2 ? some(n) : none)), none)
+    assert.deepStrictEqual(
+      _.these.traverse(option)(_.both('a', 2), n => (n >= 2 ? some(n) : none)),
+      some(_.both('a', 2))
+    )
+    assert.deepStrictEqual(_.these.traverse(option)(_.both('a', 1), n => (n >= 2 ? some(n) : none)), none)
   })
 
   it('sequence', () => {
-    const sequence = these.sequence(option)
-    const x1 = left('a')
-    assert.deepStrictEqual(sequence(x1), some(left('a')))
-    const x2 = right(some(1))
-    assert.deepStrictEqual(sequence(x2), some(right(1)))
-    const x3 = right(none)
+    const sequence = _.these.sequence(option)
+    const x1 = _.left('a')
+    assert.deepStrictEqual(sequence(x1), some(_.left('a')))
+    const x2 = _.right(some(1))
+    assert.deepStrictEqual(sequence(x2), some(_.right(1)))
+    const x3 = _.right(none)
     assert.deepStrictEqual(sequence(x3), none)
-    const x4 = both('a', some(1))
-    assert.deepStrictEqual(sequence(x4), some(both('a', 1)))
-    const x5 = both('a', none)
+    const x4 = _.both('a', some(1))
+    assert.deepStrictEqual(sequence(x4), some(_.both('a', 1)))
+    const x5 = _.both('a', none)
     assert.deepStrictEqual(sequence(x5), none)
   })
 
   it('chain', () => {
-    const M = getMonad(monoidString)
-    const f = (n: number) => (n >= 2 ? (n <= 5 ? right(n * 2) : both('bar', n)) : left('bar'))
-    assert.deepStrictEqual(M.chain(left('foo'), f), left('foo'))
-    assert.deepStrictEqual(M.chain(right(2), f), right(4))
-    assert.deepStrictEqual(M.chain(right(1), f), left('bar'))
-    assert.deepStrictEqual(M.chain(right(6), f), both('bar', 6))
-    assert.deepStrictEqual(M.chain(both('foo', 2), f), both('foo', 4))
-    assert.deepStrictEqual(M.chain(both('foo', 1), f), left('foobar'))
-    assert.deepStrictEqual(M.chain(both('foo', 6), f), both('foobar', 6))
+    const M = _.getMonad(monoidString)
+    const f = (n: number) => (n >= 2 ? (n <= 5 ? _.right(n * 2) : _.both('bar', n)) : _.left('bar'))
+    assert.deepStrictEqual(M.chain(_.left('foo'), f), _.left('foo'))
+    assert.deepStrictEqual(M.chain(_.right(2), f), _.right(4))
+    assert.deepStrictEqual(M.chain(_.right(1), f), _.left('bar'))
+    assert.deepStrictEqual(M.chain(_.right(6), f), _.both('bar', 6))
+    assert.deepStrictEqual(M.chain(_.both('foo', 2), f), _.both('foo', 4))
+    assert.deepStrictEqual(M.chain(_.both('foo', 1), f), _.left('foobar'))
+    assert.deepStrictEqual(M.chain(_.both('foo', 6), f), _.both('foobar', 6))
   })
 
   it('getLeft', () => {
-    assert.deepStrictEqual(getLeft(left('a')), some('a'))
-    assert.deepStrictEqual(getLeft(right(1)), none)
-    assert.deepStrictEqual(getLeft(both('a', 1)), some('a'))
+    assert.deepStrictEqual(_.getLeft(_.left('a')), some('a'))
+    assert.deepStrictEqual(_.getLeft(_.right(1)), none)
+    assert.deepStrictEqual(_.getLeft(_.both('a', 1)), some('a'))
   })
 
   it('getRight', () => {
-    assert.deepStrictEqual(getRight(left('a')), none)
-    assert.deepStrictEqual(getRight(right(1)), some(1))
-    assert.deepStrictEqual(getRight(both('a', 1)), some(1))
+    assert.deepStrictEqual(_.getRight(_.left('a')), none)
+    assert.deepStrictEqual(_.getRight(_.right(1)), some(1))
+    assert.deepStrictEqual(_.getRight(_.both('a', 1)), some(1))
   })
 
   it('leftOrBoth', () => {
-    assert.deepStrictEqual(leftOrBoth('a', none), left('a'))
-    assert.deepStrictEqual(leftOrBoth('a', some(1)), both('a', 1))
+    assert.deepStrictEqual(_.leftOrBoth('a', none), _.left('a'))
+    assert.deepStrictEqual(_.leftOrBoth('a', some(1)), _.both('a', 1))
   })
 
   it('rightOrBoth', () => {
-    assert.deepStrictEqual(rightOrBoth(1, none), right(1))
-    assert.deepStrictEqual(rightOrBoth(1, some('a')), both('a', 1))
+    assert.deepStrictEqual(_.rightOrBoth(1, none), _.right(1))
+    assert.deepStrictEqual(_.rightOrBoth(1, some('a')), _.both('a', 1))
   })
 
   it('getLeftOnly', () => {
-    assert.deepStrictEqual(getLeftOnly(left('a')), some('a'))
-    assert.deepStrictEqual(getLeftOnly(right(1)), none)
-    assert.deepStrictEqual(getLeftOnly(both('a', 1)), none)
+    assert.deepStrictEqual(_.getLeftOnly(_.left('a')), some('a'))
+    assert.deepStrictEqual(_.getLeftOnly(_.right(1)), none)
+    assert.deepStrictEqual(_.getLeftOnly(_.both('a', 1)), none)
   })
 
   it('getRightOnly', () => {
-    assert.deepStrictEqual(getRightOnly(left('a')), none)
-    assert.deepStrictEqual(getRightOnly(right(1)), some(1))
-    assert.deepStrictEqual(getRightOnly(both('a', 1)), none)
+    assert.deepStrictEqual(_.getRightOnly(_.left('a')), none)
+    assert.deepStrictEqual(_.getRightOnly(_.right(1)), some(1))
+    assert.deepStrictEqual(_.getRightOnly(_.both('a', 1)), none)
   })
 
   it('fromOptions', () => {
-    assert.deepStrictEqual(fromOptions(none, none), none)
-    assert.deepStrictEqual(fromOptions(some('a'), none), some(left('a')))
-    assert.deepStrictEqual(fromOptions(none, some(1)), some(right(1)))
-    assert.deepStrictEqual(fromOptions(some('a'), some(1)), some(both('a', 1)))
+    assert.deepStrictEqual(_.fromOptions(none, none), none)
+    assert.deepStrictEqual(_.fromOptions(some('a'), none), some(_.left('a')))
+    assert.deepStrictEqual(_.fromOptions(none, some(1)), some(_.right(1)))
+    assert.deepStrictEqual(_.fromOptions(some('a'), some(1)), some(_.both('a', 1)))
   })
 
   it('isLeft', () => {
-    assert.strictEqual(isLeft(left(1)), true)
-    assert.strictEqual(isLeft(right(1)), false)
-    assert.strictEqual(isLeft(both('1', 1)), false)
+    assert.strictEqual(_.isLeft(_.left(1)), true)
+    assert.strictEqual(_.isLeft(_.right(1)), false)
+    assert.strictEqual(_.isLeft(_.both('1', 1)), false)
   })
 
   it('isRight', () => {
-    assert.strictEqual(isRight(left(1)), false)
-    assert.strictEqual(isRight(right(1)), true)
-    assert.strictEqual(isRight(both('1', 1)), false)
+    assert.strictEqual(_.isRight(_.left(1)), false)
+    assert.strictEqual(_.isRight(_.right(1)), true)
+    assert.strictEqual(_.isRight(_.both('1', 1)), false)
   })
 
   it('isBoth', () => {
-    assert.strictEqual(isBoth(left(1)), false)
-    assert.strictEqual(isBoth(right(1)), false)
-    assert.strictEqual(isBoth(both('1', 1)), true)
+    assert.strictEqual(_.isBoth(_.left(1)), false)
+    assert.strictEqual(_.isBoth(_.right(1)), false)
+    assert.strictEqual(_.isBoth(_.both('1', 1)), true)
   })
 
   it('reduce', () => {
-    assert.strictEqual(these.reduce(left('b'), 'a', (b, a) => b + a), 'a')
-    assert.strictEqual(these.reduce(right('b'), 'a', (b, a) => b + a), 'ab')
-    assert.strictEqual(these.reduce(both(1, 'b'), 'a', (b, a) => b + a), 'ab')
+    assert.strictEqual(_.these.reduce(_.left('b'), 'a', (b, a) => b + a), 'a')
+    assert.strictEqual(_.these.reduce(_.right('b'), 'a', (b, a) => b + a), 'ab')
+    assert.strictEqual(_.these.reduce(_.both(1, 'b'), 'a', (b, a) => b + a), 'ab')
   })
 
   it('foldMap', () => {
-    const foldMap = these.foldMap(monoidString)
-    const x1 = right('a')
+    const foldMap = _.these.foldMap(monoidString)
+    const x1 = _.right('a')
     const f1 = identity
     assert.strictEqual(foldMap(x1, f1), 'a')
-    const x2 = left(1)
+    const x2 = _.left(1)
     assert.strictEqual(foldMap(x2, f1), '')
-    const x3 = both(1, 'a')
+    const x3 = _.both(1, 'a')
     assert.strictEqual(foldMap(x3, f1), 'a')
   })
 
   it('reduceRight', () => {
-    const reduceRight = these.reduceRight
-    const x1 = right('a')
+    const reduceRight = _.these.reduceRight
+    const x1 = _.right('a')
     const init1 = ''
     const f1 = (a: string, acc: string) => acc + a
     assert.strictEqual(reduceRight(x1, init1, f1), 'a')
-    const x2 = left(1)
+    const x2 = _.left(1)
     assert.strictEqual(reduceRight(x2, init1, f1), '')
-    const x3 = both(1, 'a')
+    const x3 = _.both(1, 'a')
     assert.strictEqual(reduceRight(x3, init1, f1), 'a')
   })
 
   it('getShow', () => {
-    const S = getShow(showString, showString)
-    assert.strictEqual(S.show(left('a')), `left("a")`)
-    assert.strictEqual(S.show(right('a')), `right("a")`)
-    assert.strictEqual(S.show(both('a', 'b')), `both("a", "b")`)
+    const S = _.getShow(showString, showString)
+    assert.strictEqual(S.show(_.left('a')), `left("a")`)
+    assert.strictEqual(S.show(_.right('a')), `right("a")`)
+    assert.strictEqual(S.show(_.both('a', 'b')), `both("a", "b")`)
   })
 })
diff --git a/test/Traced.ts b/test/Traced.ts
index 072405ee..81313156 100644
--- a/test/Traced.ts
+++ b/test/Traced.ts
@@ -1,6 +1,7 @@
 import * as assert from 'assert'
 import { getStructMonoid, monoidAny, Monoid } from '../src/Monoid'
 import { Traced, traced, getComonad, tracks, listen, listens, censor } from '../src/Traced'
+import { pipeOp as pipe } from '../src/function'
 
 // Adapted from https://chshersh.github.io/posts/2019-03-25-comonadic-builders
 
@@ -101,24 +102,35 @@ describe('Traced', () => {
   })
 
   it('listens', () => {
-    assert.deepStrictEqual(C.extract(listens(buildProject('myproject'), settings => settings.settingsTravis)), [
-      {
-        projectName: 'myproject',
-        projectHasLibrary: false,
-        projectGitHub: false,
-        projectTravis: false
-      },
-      false
-    ])
+    assert.deepStrictEqual(
+      C.extract(
+        pipe(
+          buildProject('myproject'),
+          listens(settings => settings.settingsTravis)
+        )
+      ),
+      [
+        {
+          projectName: 'myproject',
+          projectHasLibrary: false,
+          projectGitHub: false,
+          projectTravis: false
+        },
+        false
+      ]
+    )
   })
 
   it('censor', () => {
     assert.deepStrictEqual(
       C.extract(
-        censor(buildProject('myproject'), settings => ({
-          ...settings,
-          settingsHasLibrary: !settings.settingsHasLibrary
-        }))
+        pipe(
+          buildProject('myproject'),
+          censor(settings => ({
+            ...settings,
+            settingsHasLibrary: !settings.settingsHasLibrary
+          }))
+        )
       ),
       {
         projectName: 'myproject',
diff --git a/test/Writer.ts b/test/Writer.ts
index a221bc78..84bccfe6 100644
--- a/test/Writer.ts
+++ b/test/Writer.ts
@@ -1,6 +1,6 @@
 import * as assert from 'assert'
 import * as W from '../src/Writer'
-import { tuple } from '../src/function'
+import { tuple, pipeOp as pipe } from '../src/function'
 import { monoidString } from '../src/Monoid'
 
 describe('Writer', () => {
@@ -30,11 +30,25 @@ describe('Writer', () => {
   })
 
   it('listens', () => {
-    assert.deepStrictEqual(W.listens(() => [1, 'a'], w => w.length)(), [[1, 1], 'a'])
+    const fa: W.Writer<string, number> = () => [1, 'a']
+    assert.deepStrictEqual(
+      pipe(
+        fa,
+        W.listens(w => w.length)
+      )(),
+      [[1, 1], 'a']
+    )
   })
 
   it('censor', () => {
-    assert.deepStrictEqual(W.censor(() => [1, ['a', 'b']], w => w.filter(a => a !== 'a'))(), [1, ['b']])
+    const fa: W.Writer<Array<string>, number> = () => [1, ['a', 'b']]
+    assert.deepStrictEqual(
+      pipe(
+        fa,
+        W.censor(w => w.filter(a => a !== 'a'))
+      )(),
+      [1, ['b']]
+    )
   })
 
   it('getMonad', () => {
diff --git a/test/fluent.ts b/test/fluent.ts
index 77cecb48..1c301da3 100644
--- a/test/fluent.ts
+++ b/test/fluent.ts
@@ -31,7 +31,7 @@ const fluent = F.fluent(option)
 describe('fluent', () => {
   it('apply', () => {
     const fluent = F.fluent(option)
-    assert.strictEqual(fluent(some(1)).apply(o => fold(o, () => 'none', a => `some(${a})`)), 'some(1)')
+    assert.strictEqual(fluent(some(1)).apply(fold(() => 'none', a => `some(${a})`)), 'some(1)')
   })
 
   it('pipe', () => {
@@ -46,8 +46,8 @@ describe('fluent', () => {
     const x: X = { a: { b: { c: 1 } } }
     assert.deepStrictEqual(
       fluent(fromNullable(x.a))
-        .pipe(o => mapNullable(o, x => x.b))
-        .apply(o => mapNullable(o, x => x.c)),
+        .pipe(mapNullable(x => x.b))
+        .apply(mapNullable(x => x.c)),
       some(1)
     )
   })