Repository: gcanti/fp-ts
Pull request #1762 (2022-09-05 15:58:29)

docs: add examples to getApplicativeValidation / getAltValidation


Patch:
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 00000000..7c2e87df
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1,1 @@
+github: [gcanti]
diff --git a/docs/modules/Either.ts.md b/docs/modules/Either.ts.md
index f6a63a3f..e970508d 100644
--- a/docs/modules/Either.ts.md
+++ b/docs/modules/Either.ts.md
@@ -1195,22 +1195,93 @@ Added in v2.0.0
 
 ## getAltValidation
 
+The default [`Alt`](#alt) instance returns the last error, if you want to
+get all errors you need to provide an way to concatenate them via a `Semigroup`.
+
 **Signature**
 
 ```ts
 export declare const getAltValidation: <E>(SE: Semigroup<E>) => Alt2C<'Either', E>
 ```
 
+**Example**
+
+```ts
+import * as E from 'fp-ts/Either'
+import { pipe } from 'fp-ts/function'
+import * as S from 'fp-ts/Semigroup'
+import * as string from 'fp-ts/string'
+
+const parseString = (u: unknown): E.Either<string, string> =>
+  typeof u === 'string' ? E.right(u) : E.left('not a string')
+
+const parseNumber = (u: unknown): E.Either<string, number> =>
+  typeof u === 'number' ? E.right(u) : E.left('not a number')
+
+const parse = (u: unknown): E.Either<string, string | number> =>
+  pipe(
+    parseString(u),
+    E.alt<string, string | number>(() => parseNumber(u))
+  )
+
+assert.deepStrictEqual(parse(true), E.left('not a number')) // <= last error
+
+const Alt = E.getAltValidation(pipe(string.Semigroup, S.intercalate(', ')))
+
+const parseAll = (u: unknown): E.Either<string, string | number> =>
+  Alt.alt<string | number>(parseString(u), () => parseNumber(u))
+
+assert.deepStrictEqual(parseAll(true), E.left('not a string, not a number')) // <= all errors
+```
+
 Added in v2.7.0
 
 ## getApplicativeValidation
 
+The default [`Applicative`](#applicative) instance returns the first error, if you want to
+get all errors you need to provide an way to concatenate them via a `Semigroup`.
+
 **Signature**
 
 ```ts
 export declare const getApplicativeValidation: <E>(SE: Semigroup<E>) => Applicative2C<'Either', E>
 ```
 
+**Example**
+
+```ts
+import * as A from 'fp-ts/Apply'
+import * as E from 'fp-ts/Either'
+import { pipe } from 'fp-ts/function'
+import * as S from 'fp-ts/Semigroup'
+import * as string from 'fp-ts/string'
+
+const parseString = (u: unknown): E.Either<string, string> =>
+  typeof u === 'string' ? E.right(u) : E.left('not a string')
+
+const parseNumber = (u: unknown): E.Either<string, number> =>
+  typeof u === 'number' ? E.right(u) : E.left('not a number')
+
+interface Person {
+  readonly name: string
+  readonly age: number
+}
+
+const parsePerson = (input: Record<string, unknown>): E.Either<string, Person> =>
+  pipe(E.Do, E.apS('name', parseString(input.name)), E.apS('age', parseNumber(input.age)))
+
+assert.deepStrictEqual(parsePerson({}), E.left('not a string')) // <= first error
+
+const Applicative = E.getApplicativeValidation(pipe(string.Semigroup, S.intercalate(', ')))
+
+const apS = A.apS(Applicative)
+
+const parsePersonAll = (input: Record<string, unknown>): E.Either<string, Person> =>
+  pipe(E.Do, apS('name', parseString(input.name)), apS('age', parseNumber(input.age)))
+
+assert.deepStrictEqual(parsePersonAll({}), E.left('not a string, not a number')) // <= all errors
+```
+
 Added in v2.7.0
 
 ## getCompactable
diff --git a/docs/modules/IOEither.ts.md b/docs/modules/IOEither.ts.md
index ff04ab78..d3949e99 100644
--- a/docs/modules/IOEither.ts.md
+++ b/docs/modules/IOEither.ts.md
@@ -989,6 +989,11 @@ Added in v2.0.0
 
 ## getAltIOValidation
 
+The default [`Alt`](#alt) instance returns the last error, if you want to
+get all errors you need to provide an way to concatenate them via a `Semigroup`.
+
+See [`getAltValidation`](./Either.ts.html#getaltvalidation).
+
 **Signature**
 
 ```ts
@@ -999,6 +1004,11 @@ Added in v2.7.0
 
 ## getApplicativeIOValidation
 
+The default [`ApplicativePar`](#applicativepar) instance returns the first error, if you want to
+get all errors you need to provide an way to concatenate them via a `Semigroup`.
+
+See [`getApplicativeValidation`](./Either.ts.html#getapplicativevalidation).
+
 **Signature**
 
 ```ts
diff --git a/docs/modules/ReaderEither.ts.md b/docs/modules/ReaderEither.ts.md
index df9f6500..f8f463fe 100644
--- a/docs/modules/ReaderEither.ts.md
+++ b/docs/modules/ReaderEither.ts.md
@@ -1088,6 +1088,11 @@ Added in v2.0.0
 
 ## getAltReaderValidation
 
+The default [`Alt`](#alt) instance returns the last error, if you want to
+get all errors you need to provide an way to concatenate them via a `Semigroup`.
+
+See [`getAltValidation`](./Either.ts.html#getaltvalidation).
+
 **Signature**
 
 ```ts
@@ -1098,6 +1103,11 @@ Added in v2.7.0
 
 ## getApplicativeReaderValidation
 
+The default [`Applicative`](#applicative) instance returns the first error, if you want to
+get all errors you need to provide an way to concatenate them via a `Semigroup`.
+
+See [`getApplicativeValidation`](./Either.ts.html#getapplicativevalidation).
+
 **Signature**
 
 ```ts
diff --git a/docs/modules/ReaderTaskEither.ts.md b/docs/modules/ReaderTaskEither.ts.md
index 2580d8af..33b3c5e6 100644
--- a/docs/modules/ReaderTaskEither.ts.md
+++ b/docs/modules/ReaderTaskEither.ts.md
@@ -1599,6 +1599,11 @@ Added in v2.0.0
 
 ## getAltReaderTaskValidation
 
+The default [`Alt`](#alt) instance returns the last error, if you want to
+get all errors you need to provide an way to concatenate them via a `Semigroup`.
+
+See [`getAltValidation`](./Either.ts.html#getaltvalidation).
+
 **Signature**
 
 ```ts
@@ -1609,6 +1614,11 @@ Added in v2.7.0
 
 ## getApplicativeReaderTaskValidation
 
+The default [`ApplicativePar`](#applicativepar) instance returns the first error, if you want to
+get all errors you need to provide an way to concatenate them via a `Semigroup`.
+
+See [`getApplicativeValidation`](./Either.ts.html#getapplicativevalidation).
+
 **Signature**
 
 ```ts
diff --git a/docs/modules/TaskEither.ts.md b/docs/modules/TaskEither.ts.md
index 19963869..c84e355b 100644
--- a/docs/modules/TaskEither.ts.md
+++ b/docs/modules/TaskEither.ts.md
@@ -1252,6 +1252,11 @@ Added in v2.0.0
 
 ## getAltTaskValidation
 
+The default [`Alt`](#alt) instance returns the last error, if you want to
+get all errors you need to provide an way to concatenate them via a `Semigroup`.
+
+See [`getAltValidation`](./Either.ts.html#getaltvalidation).
+
 **Signature**
 
 ```ts
@@ -1262,6 +1267,11 @@ Added in v2.7.0
 
 ## getApplicativeTaskValidation
 
+The default [`ApplicativePar`](#applicativepar) instance returns the first error, if you want to
+get all errors you need to provide an way to concatenate them via a `Semigroup`.
+
+See [`getApplicativeValidation`](./Either.ts.html#getapplicativevalidation).
+
 **Signature**
 
 ```ts
diff --git a/src/Chain.ts b/src/Chain.ts
index 5d29e4c4..a61a7b83 100644
--- a/src/Chain.ts
+++ b/src/Chain.ts
@@ -115,49 +115,49 @@ export function bind<M extends URIS4>(
   M: Chain4<M>
 ): <N extends string, A, S, R, E, B>(
   name: Exclude<N, keyof A>,
-  f: (a: A) => Kind4<M, S, R, E, B>
+  f: <A2 extends A>(a: A | A2) => Kind4<M, S, R, E, B>
 ) => (ma: Kind4<M, S, R, E, A>) => Kind4<M, S, R, E, { readonly [K in keyof A | N]: K extends keyof A ? A[K] : B }>
 export function bind<M extends URIS3>(
   M: Chain3<M>
 ): <N extends string, A, R, E, B>(
   name: Exclude<N, keyof A>,
-  f: (a: A) => Kind3<M, R, E, B>
+  f: <A2 extends A>(a: A | A2) => Kind3<M, R, E, B>
 ) => (ma: Kind3<M, R, E, A>) => Kind3<M, R, E, { readonly [K in keyof A | N]: K extends keyof A ? A[K] : B }>
 export function bind<M extends URIS3, E>(
   M: Chain3C<M, E>
 ): <N extends string, A, R, B>(
   name: Exclude<N, keyof A>,
-  f: (a: A) => Kind3<M, R, E, B>
+  f: <A2 extends A>(a: A | A2) => Kind3<M, R, E, B>
 ) => (ma: Kind3<M, R, E, A>) => Kind3<M, R, E, { readonly [K in keyof A | N]: K extends keyof A ? A[K] : B }>
 export function bind<M extends URIS2>(
   M: Chain2<M>
 ): <N extends string, A, E, B>(
   name: Exclude<N, keyof A>,
-  f: (a: A) => Kind2<M, E, B>
+  f: <A2 extends A>(a: A | A2) => Kind2<M, E, B>
 ) => (ma: Kind2<M, E, A>) => Kind2<M, E, { readonly [K in keyof A | N]: K extends keyof A ? A[K] : B }>
 export function bind<M extends URIS2, E>(
   M: Chain2C<M, E>
 ): <N extends string, A, B>(
   name: Exclude<N, keyof A>,
-  f: (a: A) => Kind2<M, E, B>
+  f: <A2 extends A>(a: A | A2) => Kind2<M, E, B>
 ) => (ma: Kind2<M, E, A>) => Kind2<M, E, { readonly [K in keyof A | N]: K extends keyof A ? A[K] : B }>
 export function bind<M extends URIS>(
   M: Chain1<M>
 ): <N extends string, A, B>(
   name: Exclude<N, keyof A>,
-  f: (a: A) => Kind<M, B>
+  f: <A2 extends A>(a: A | A2) => Kind<M, B>
 ) => (ma: Kind<M, A>) => Kind<M, { readonly [K in keyof A | N]: K extends keyof A ? A[K] : B }>
 export function bind<M>(
   M: Chain<M>
 ): <N extends string, A, B>(
   name: Exclude<N, keyof A>,
-  f: (a: A) => HKT<M, B>
+  f: <A2 extends A>(a: A | A2) => HKT<M, B>
 ) => (ma: HKT<M, A>) => HKT<M, { readonly [K in keyof A | N]: K extends keyof A ? A[K] : B }>
 export function bind<M>(
   M: Chain<M>
 ): <N extends string, A, B>(
   name: Exclude<N, keyof A>,
-  f: (a: A) => HKT<M, B>
+  f: <A2 extends A>(a: A | A2) => HKT<M, B>
 ) => (ma: HKT<M, A>) => HKT<M, { readonly [K in keyof A | N]: K extends keyof A ? A[K] : B }> {
   return (name, f) => (ma) => M.chain(ma, (a) => M.map(f(a), (b) => Object.assign({}, a, { [name]: b }) as any))
 }
diff --git a/src/Either.ts b/src/Either.ts
index 4eb76a30..704f7ee5 100644
--- a/src/Either.ts
+++ b/src/Either.ts
@@ -346,6 +346,55 @@ export const getWitherable = <E>(M: Monoid<E>): Witherable2C<URI, E> => {
 }
 
 /**
+ * The default [`Applicative`](#applicative) instance returns the first error, if you want to
+ * get all errors you need to provide an way to concatenate them via a `Semigroup`.
+ *
+ * @example
+ * import * as A from 'fp-ts/Apply'
+ * import * as E from 'fp-ts/Either'
+ * import { pipe } from 'fp-ts/function'
+ * import * as S from 'fp-ts/Semigroup'
+ * import * as string from 'fp-ts/string'
+ *
+ * const parseString = (u: unknown): E.Either<string, string> =>
+ *   typeof u === 'string' ? E.right(u) : E.left('not a string')
+ *
+ * const parseNumber = (u: unknown): E.Either<string, number> =>
+ *   typeof u === 'number' ? E.right(u) : E.left('not a number')
+ *
+ * interface Person {
+ *   readonly name: string
+ *   readonly age: number
+ * }
+ *
+ * const parsePerson = (
+ *   input: Record<string, unknown>
+ * ): E.Either<string, Person> =>
+ *   pipe(
+ *     E.Do,
+ *     E.apS('name', parseString(input.name)),
+ *     E.apS('age', parseNumber(input.age))
+ *   )
+ *
+ * assert.deepStrictEqual(parsePerson({}), E.left('not a string')) // <= first error
+ *
+ * const Applicative = E.getApplicativeValidation(
+ *   pipe(string.Semigroup, S.intercalate(', '))
+ * )
+ *
+ * const apS = A.apS(Applicative)
+ *
+ * const parsePersonAll = (
+ *   input: Record<string, unknown>
+ * ): E.Either<string, Person> =>
+ *   pipe(
+ *     E.Do,
+ *     apS('name', parseString(input.name)),
+ *     apS('age', parseNumber(input.age))
+ *   )
+ *
+ * assert.deepStrictEqual(parsePersonAll({}), E.left('not a string, not a number')) // <= all errors
+ *
  * @category instances
  * @since 2.7.0
  */
@@ -365,6 +414,36 @@ export const getApplicativeValidation = <E>(SE: Semigroup<E>): Applicative2C<URI
 })
 
 /**
+ * The default [`Alt`](#alt) instance returns the last error, if you want to
+ * get all errors you need to provide an way to concatenate them via a `Semigroup`.
+ *
+ * @example
+ * import * as E from 'fp-ts/Either'
+ * import { pipe } from 'fp-ts/function'
+ * import * as S from 'fp-ts/Semigroup'
+ * import * as string from 'fp-ts/string'
+ *
+ * const parseString = (u: unknown): E.Either<string, string> =>
+ *   typeof u === 'string' ? E.right(u) : E.left('not a string')
+ *
+ * const parseNumber = (u: unknown): E.Either<string, number> =>
+ *   typeof u === 'number' ? E.right(u) : E.left('not a number')
+ *
+ * const parse = (u: unknown): E.Either<string, string | number> =>
+ *   pipe(
+ *     parseString(u),
+ *     E.alt<string, string | number>(() => parseNumber(u))
+ *   )
+ *
+ * assert.deepStrictEqual(parse(true), E.left('not a number')) // <= last error
+ *
+ * const Alt = E.getAltValidation(pipe(string.Semigroup, S.intercalate(', ')))
+ *
+ * const parseAll = (u: unknown): E.Either<string, string | number> =>
+ *   Alt.alt<string | number>(parseString(u), () => parseNumber(u))
+ *
+ * assert.deepStrictEqual(parseAll(true), E.left('not a string, not a number')) // <= all errors
+ *
  * @category instances
  * @since 2.7.0
  */
@@ -1403,7 +1482,7 @@ export const bind = /*#__PURE__*/ bind_(Chain)
  */
 export const bindW: <N extends string, A, E2, B>(
   name: Exclude<N, keyof A>,
-  f: (a: A) => Either<E2, B>
+  f: <A2 extends A>(a: A | A2) => Either<E2, B>
 ) => <E1>(
   fa: Either<E1, A>
 ) => Either<E1 | E2, { readonly [K in keyof A | N]: K extends keyof A ? A[K] : B }> = bind as any
diff --git a/src/IOEither.ts b/src/IOEither.ts
index 07e1b994..5e2f7c78 100644
--- a/src/IOEither.ts
+++ b/src/IOEither.ts
@@ -470,6 +470,11 @@ declare module './HKT' {
 }
 
 /**
+ * The default [`ApplicativePar`](#applicativepar) instance returns the first error, if you want to
+ * get all errors you need to provide an way to concatenate them via a `Semigroup`.
+ *
+ * See [`getApplicativeValidation`](./Either.ts.html#getapplicativevalidation).
+ *
  * @category instances
  * @since 2.7.0
  */
@@ -485,6 +490,11 @@ export function getApplicativeIOValidation<E>(S: Semigroup<E>): Applicative2C<UR
 }
 
 /**
+ * The default [`Alt`](#alt) instance returns the last error, if you want to
+ * get all errors you need to provide an way to concatenate them via a `Semigroup`.
+ *
+ * See [`getAltValidation`](./Either.ts.html#getaltvalidation).
+ *
  * @category instances
  * @since 2.7.0
  */
@@ -948,7 +958,7 @@ export const bind = /*#__PURE__*/ bind_(Chain)
  */
 export const bindW: <N extends string, A, E2, B>(
   name: Exclude<N, keyof A>,
-  f: (a: A) => IOEither<E2, B>
+  f: <A2 extends A>(a: A | A2) => IOEither<E2, B>
 ) => <E1>(
   fa: IOEither<E1, A>
 ) => IOEither<E1 | E2, { readonly [K in keyof A | N]: K extends keyof A ? A[K] : B }> = bind as any
diff --git a/src/Reader.ts b/src/Reader.ts
index a2dcc7e0..82e80c4c 100644
--- a/src/Reader.ts
+++ b/src/Reader.ts
@@ -506,7 +506,7 @@ export const bind = /*#__PURE__*/ bind_(Chain)
  */
 export const bindW: <N extends string, A, R2, B>(
   name: Exclude<N, keyof A>,
-  f: (a: A) => Reader<R2, B>
+  f: <A2 extends A>(a: A | A2) => Reader<R2, B>
 ) => <R1>(
   fa: Reader<R1, A>
 ) => Reader<R1 & R2, { readonly [K in keyof A | N]: K extends keyof A ? A[K] : B }> = bind as any
diff --git a/src/ReaderEither.ts b/src/ReaderEither.ts
index f26e4381..ada73edc 100644
--- a/src/ReaderEither.ts
+++ b/src/ReaderEither.ts
@@ -515,6 +515,11 @@ export function getFilterable<E>(M: Monoid<E>): Filterable3C<URI, E> {
 }
 
 /**
+ * The default [`Applicative`](#applicative) instance returns the first error, if you want to
+ * get all errors you need to provide an way to concatenate them via a `Semigroup`.
+ *
+ * See [`getApplicativeValidation`](./Either.ts.html#getapplicativevalidation).
+ *
  * @category instances
  * @since 2.7.0
  */
@@ -530,6 +535,11 @@ export function getApplicativeReaderValidation<E>(S: Semigroup<E>): Applicative3
 }
 
 /**
+ * The default [`Alt`](#alt) instance returns the last error, if you want to
+ * get all errors you need to provide an way to concatenate them via a `Semigroup`.
+ *
+ * See [`getAltValidation`](./Either.ts.html#getaltvalidation).
+ *
  * @category instances
  * @since 2.7.0
  */
@@ -938,7 +948,7 @@ export const bind = /*#__PURE__*/ bind_(Chain)
  */
 export const bindW: <N extends string, A, R2, E2, B>(
   name: Exclude<N, keyof A>,
-  f: (a: A) => ReaderEither<R2, E2, B>
+  f: <A2 extends A>(a: A | A2) => ReaderEither<R2, E2, B>
 ) => <R1, E1>(
   fa: ReaderEither<R1, E1, A>
 ) => ReaderEither<R1 & R2, E1 | E2, { readonly [K in keyof A | N]: K extends keyof A ? A[K] : B }> = bind as any
diff --git a/src/ReaderIO.ts b/src/ReaderIO.ts
index 44d2dedd..79a6252d 100644
--- a/src/ReaderIO.ts
+++ b/src/ReaderIO.ts
@@ -437,7 +437,7 @@ export const bind = /*#__PURE__*/ bind_(Chain)
  */
 export const bindW: <N extends string, A, R2, B>(
   name: Exclude<N, keyof A>,
-  f: (a: A) => ReaderIO<R2, B>
+  f: <A2 extends A>(a: A | A2) => ReaderIO<R2, B>
 ) => <R1>(
   fa: ReaderIO<R1, A>
 ) => ReaderIO<R1 & R2, { readonly [K in keyof A | N]: K extends keyof A ? A[K] : B }> = bind as any
diff --git a/src/ReaderTask.ts b/src/ReaderTask.ts
index 8d9e6b84..26a853b9 100644
--- a/src/ReaderTask.ts
+++ b/src/ReaderTask.ts
@@ -541,7 +541,7 @@ export const bind = /*#__PURE__*/ bind_(Chain)
  */
 export const bindW: <N extends string, A, R2, B>(
   name: Exclude<N, keyof A>,
-  f: (a: A) => ReaderTask<R2, B>
+  f: <A2 extends A>(a: A | A2) => ReaderTask<R2, B>
 ) => <R1>(
   fa: ReaderTask<R1, A>
 ) => ReaderTask<R1 & R2, { readonly [K in keyof A | N]: K extends keyof A ? A[K] : B }> = bind as any
diff --git a/src/ReaderTaskEither.ts b/src/ReaderTaskEither.ts
index d0c30d66..ee512252 100644
--- a/src/ReaderTaskEither.ts
+++ b/src/ReaderTaskEither.ts
@@ -783,6 +783,11 @@ export function getFilterable<E>(M: Monoid<E>): Filterable3C<URI, E> {
 }
 
 /**
+ * The default [`ApplicativePar`](#applicativepar) instance returns the first error, if you want to
+ * get all errors you need to provide an way to concatenate them via a `Semigroup`.
+ *
+ * See [`getApplicativeValidation`](./Either.ts.html#getapplicativevalidation).
+ *
  * @category instances
  * @since 2.7.0
  */
@@ -798,6 +803,11 @@ export function getApplicativeReaderTaskValidation<E>(A: Apply1<T.URI>, S: Semig
 }
 
 /**
+ * The default [`Alt`](#alt) instance returns the last error, if you want to
+ * get all errors you need to provide an way to concatenate them via a `Semigroup`.
+ *
+ * See [`getAltValidation`](./Either.ts.html#getaltvalidation).
+ *
  * @category instances
  * @since 2.7.0
  */
@@ -1408,7 +1418,7 @@ export const bind = /*#__PURE__*/ bind_(Chain)
  */
 export const bindW: <N extends string, A, R2, E2, B>(
   name: Exclude<N, keyof A>,
-  f: (a: A) => ReaderTaskEither<R2, E2, B>
+  f: <A2 extends A>(a: A | A2) => ReaderTaskEither<R2, E2, B>
 ) => <R1, E1>(
   fa: ReaderTaskEither<R1, E1, A>
 ) => ReaderTaskEither<R1 & R2, E1 | E2, { readonly [K in keyof A | N]: K extends keyof A ? A[K] : B }> = bind as any
diff --git a/src/StateReaderTaskEither.ts b/src/StateReaderTaskEither.ts
index 94c55b65..c769c808 100644
--- a/src/StateReaderTaskEither.ts
+++ b/src/StateReaderTaskEither.ts
@@ -1125,7 +1125,7 @@ export const bind = /*#__PURE__*/ bind_(Chain)
  */
 export const bindW: <N extends string, A, S, R2, E2, B>(
   name: Exclude<N, keyof A>,
-  f: (a: A) => StateReaderTaskEither<S, R2, E2, B>
+  f: <A2 extends A>(a: A | A2) => StateReaderTaskEither<S, R2, E2, B>
 ) => <R1, E1>(
   fa: StateReaderTaskEither<S, R1, E1, A>
 ) => StateReaderTaskEither<
diff --git a/src/TaskEither.ts b/src/TaskEither.ts
index 9806fc26..4ef20597 100644
--- a/src/TaskEither.ts
+++ b/src/TaskEither.ts
@@ -681,6 +681,11 @@ declare module './HKT' {
 }
 
 /**
+ * The default [`ApplicativePar`](#applicativepar) instance returns the first error, if you want to
+ * get all errors you need to provide an way to concatenate them via a `Semigroup`.
+ *
+ * See [`getApplicativeValidation`](./Either.ts.html#getapplicativevalidation).
+ *
  * @category instances
  * @since 2.7.0
  */
@@ -696,6 +701,11 @@ export function getApplicativeTaskValidation<E>(A: Apply1<T.URI>, S: Semigroup<E
 }
 
 /**
+ * The default [`Alt`](#alt) instance returns the last error, if you want to
+ * get all errors you need to provide an way to concatenate them via a `Semigroup`.
+ *
+ * See [`getAltValidation`](./Either.ts.html#getaltvalidation).
+ *
  * @category instances
  * @since 2.7.0
  */
@@ -1269,7 +1279,7 @@ export const bind = /*#__PURE__*/ bind_(Chain)
  */
 export const bindW: <N extends string, A, E2, B>(
   name: Exclude<N, keyof A>,
-  f: (a: A) => TaskEither<E2, B>
+  f: <A2 extends A>(a: A | A2) => TaskEither<E2, B>
 ) => <E1>(
   fa: TaskEither<E1, A>
 ) => TaskEither<E1 | E2, { readonly [K in keyof A | N]: K extends keyof A ? A[K] : B }> = bind as any


Test patch:
diff --git a/test/TaskEither.ts b/test/TaskEither.ts
index 8637ab13..3cef2865 100644
--- a/test/TaskEither.ts
+++ b/test/TaskEither.ts
@@ -622,6 +622,52 @@ describe('TaskEither', () => {
     )
   })
 
+  it('do notation ensuring proper param passthrough', async () => {
+    const c = (p: { readonly a: number }) => _.right<string, number>(p.a)
+    const d = (p: { readonly b: string }) => _.right<string, string>(p.b)
+    U.deepStrictEqual(
+      await pipe(
+        _.right<string, number>(1),
+        _.bindTo('a'),
+        _.bind('b', () => _.right('b')),
+        _.bind('c', c),
+        _.bind('d', d),
+        _.bind(
+          'e',
+          _.fromOptionK(() => 'err')((p: { readonly c: number }) => some(p.c))
+        ),
+        _.bind(
+          'f',
+          _.fromOptionK(() => 'err')((p) => some(p.b))
+        )
+      )(),
+      E.right({ a: 1, b: 'b', c: 1, d: 'b', e: 1, f: 'b' })
+    )
+  })
+
+  it('do notation bindW ensuring proper param passthrough', async () => {
+    const c = (p: { readonly a: number }) => _.right<string, number>(p.a)
+    const d = (p: { readonly b: string }) => _.right<string, string>(p.b)
+    U.deepStrictEqual(
+      await pipe(
+        _.right<string, number>(1),
+        _.bindTo('a'),
+        _.bindW('b', () => _.right('b')),
+        _.bindW('c', c),
+        _.bindW('d', d),
+        _.bindW(
+          'e',
+          _.fromOptionK(() => 1)((p: { readonly c: number }) => some(p.c))
+        ),
+        _.bindW(
+          'f',
+          _.fromOptionK(() => ({ err: 'err' }))((p) => some(p.b))
+        )
+      )(),
+      E.right({ a: 1, b: 'b', c: 1, d: 'b', e: 1, f: 'b' })
+    )
+  })
+
   it('apS', async () => {
     U.deepStrictEqual(
       await pipe(_.right<string, number>(1), _.bindTo('a'), _.apS('b', _.right('b')))(),