Repository: gcanti/fp-ts
Pull request #1345 (2020-10-30 13:13:15)

solution for stack safe & better performance for array sequence
I think I explain most of things that I want to do [here](https://github.com/gcanti/fp-ts/issues/1344)
I've got the idea from [this issue](https://github.com/gcanti/fp-ts/issues/1315)
the idea is that I add a function that `sequence`  array to data type, it does not use `ap` so it's stack safe and perform better.
the question that I have is that I don't know if it's name `sequenceA` make sense or not. 🤔
this pull request is draft until I commit all these data types.

- [x] Either

- [x] Option

- [x] Task

- [x] TaskSeq

- [x] IO

- [x] Reader

- [x] State

- [x] TaskEither

- [x] TaskEitherSeq 

- [x] IOEither

- [x] IOEitherSeq

- [x] ReaderTask

- [x] ReaderTaskSeq

- [x] ReaderEither

- [x] ReaderTaskEither

- [x] ReaderTaskEitherSeq

- [x] StateReaderTaskEither

mohaalak: I have another problem for naming I wrote the `sequenceA` for `Task` it's the parallel version, what name should I give to sequential `sequenceSeqA`?

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index adf0a651..33cb194c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -66,11 +66,6 @@ high state of flux, you're at risk of it changing without notice.
   - `Option`
     - deprecate `mapNullable` in favour of `chainNullableK` (@gcanti)
 
-# 2.8.6
-
-- **Bug Fix**
-  - fix #1350 (@gcanti)
-
 # 2.8.5
 
 - **Polish**
diff --git a/docs/index.md b/docs/index.md
index e0f7e23f..e3f0ae64 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -29,7 +29,7 @@ Data types are the practical part of `fp-ts`: you can instantiate them with your
 
 Many functions in `fp-ts` use [ad hoc polymorphism](https://en.wikipedia.org/wiki/Ad_hoc_polymorphism), meaning that they have a single implementation that can deal with arguments of different types. To make this work, it is often necessary to provide a data type _instance_ that provides functionality that is specific to the data type.
 
-**Note**. Data types are not stack safe and there is no trampolining implementation.
+**Note**. Data types are not stack safe and there is no trampolining implementation. But for traversing and sequencing lists there is a stack safe and optimized version in each data types.
 
 ## Type Classes
 
diff --git a/docs/modules/Array.ts.md b/docs/modules/Array.ts.md
index 259fcbdf..dd686a33 100644
--- a/docs/modules/Array.ts.md
+++ b/docs/modules/Array.ts.md
@@ -471,6 +471,8 @@ Added in v2.0.0
 
 ## sequence
 
+**for optimized and stack safe version check the data types `sequenceArray` function**
+
 **Signature**
 
 ```ts
@@ -481,6 +483,8 @@ Added in v2.6.3
 
 ## traverse
 
+**for optimized and stack safe version check the data types `traverseArray` function**
+
 **Signature**
 
 ```ts
@@ -493,6 +497,8 @@ Added in v2.6.3
 
 ## traverseWithIndex
 
+**for optimized and stack safe version check the data types `traverseArrayWithIndex` function**
+
 **Signature**
 
 ```ts
diff --git a/docs/modules/Either.ts.md b/docs/modules/Either.ts.md
index 102a3a69..fbdf9514 100644
--- a/docs/modules/Either.ts.md
+++ b/docs/modules/Either.ts.md
@@ -120,7 +120,10 @@ Added in v2.0.0
   - [bindW](#bindw)
   - [elem](#elem)
   - [exists](#exists)
+  - [sequenceArray](#sequencearray)
   - [toError](#toerror)
+  - [traverseArray](#traversearray)
+  - [traverseArrayWithIndex](#traversearraywithindex)
 
 ---
 
@@ -1415,6 +1418,31 @@ assert.strictEqual(gt2(right(3)), true)
 
 Added in v2.0.0
 
+## sequenceArray
+
+convert an array of either to an either of array
+this function have the same behavior of `A.sequence(E.either)` but it's optimized and perform better
+
+**Signature**
+
+```ts
+export declare const sequenceArray: <E, A>(arr: readonly Either<E, A>[]) => Either<E, readonly A[]>
+```
+
+**Example**
+
+```ts
+import { sequenceArray, left, right } from 'fp-ts/Either'
+import { pipe } from 'fp-ts/function'
+import * as A from 'fp-ts/Array'
+
+const arr = A.range(0, 10)
+assert.deepStrictEqual(pipe(arr, A.map(right), sequenceArray), right(arr))
+assert.deepStrictEqual(pipe(arr, A.map(right), A.cons(left('Error')), sequenceArray), left('Error'))
+```
+
+Added in v2.9.0
+
 ## toError
 
 Default value for the `onError` argument of `tryCatch`
@@ -1426,3 +1454,59 @@ export declare function toError(e: unknown): Error
 ```
 
 Added in v2.0.0
+
+## traverseArray
+
+map an array using provided function to Either then transform to Either of the array
+this function have the same behavior of `A.traverse(E.either)` but it's optimized and perform better
+
+**Signature**
+
+```ts
+export declare const traverseArray: <E, A, B>(
+  f: (a: A) => Either<E, B>
+) => (arr: readonly A[]) => Either<E, readonly B[]>
+```
+
+**Example**
+
+```ts
+import { traverseArray, left, right, fromPredicate } from 'fp-ts/Either'
+import { pipe } from 'fp-ts/function'
+import * as A from 'fp-ts/Array'
+
+const arr = A.range(0, 10)
+assert.deepStrictEqual(
+  pipe(
+    arr,
+    traverseArray((x) => right(x))
+  ),
+  right(arr)
+)
+assert.deepStrictEqual(
+  pipe(
+    arr,
+    traverseArray(
+      fromPredicate(
+        (x) => x > 5,
+        () => 'a'
+      )
+    )
+  ),
+  left('a')
+)
+```
+
+Added in v2.9.0
+
+## traverseArrayWithIndex
+
+**Signature**
+
+```ts
+export declare const traverseArrayWithIndex: <E, A, B>(
+  f: (index: number, a: A) => Either<E, B>
+) => (arr: readonly A[]) => Either<E, readonly B[]>
+```
+
+Added in v2.9.0
diff --git a/docs/modules/IO.ts.md b/docs/modules/IO.ts.md
index 3dcd469f..e01f32e6 100644
--- a/docs/modules/IO.ts.md
+++ b/docs/modules/IO.ts.md
@@ -54,6 +54,9 @@ Added in v2.0.0
   - [apS](#aps)
   - [bind](#bind)
   - [bindTo](#bindto)
+  - [sequenceArray](#sequencearray)
+  - [traverseArray](#traversearray)
+  - [traverseArrayWithIndex](#traversearraywithindex)
 
 ---
 
@@ -336,3 +339,63 @@ export declare const bindTo: <N extends string>(name: N) => <A>(fa: IO<A>) => IO
 ```
 
 Added in v2.8.0
+
+## sequenceArray
+
+transform Array of IO to IO of Array
+
+this function have the same behavior of `A.sequence(IO.io)` but it's stack safe
+
+```ts
+import * as RA from 'fp-ts/ReadonlyArray'
+import { sequenceArray, IO } from 'fp-ts/IO'
+import { pipe } from 'fp-ts/function'
+
+const log: <A>(x: A) => IO<void> = (x) => () => console.log(x)
+
+pipe(RA.range(0, 100), RA.map(log), sequenceA)() // it now prints 0 to 100
+```
+
+**Signature**
+
+```ts
+export declare const sequenceArray: <A>(arr: readonly IO<A>[]) => IO<readonly A[]>
+```
+
+Added in v2.9.0
+
+## traverseArray
+
+runs an action for every element in array, and accumulates the results IO in the array.
+
+this function have the same behavior of `A.traverse(IO.io)` but it's stack safe
+
+```ts
+import * as RA from 'fp-ts/ReadonlyArray'
+import { traverseArray, IO } from 'fp-ts/IO'
+import { pipe } from 'fp-ts/function'
+
+const log: <A>(x: A) => IO<void> = (x) => () => console.log(x)
+
+pipe(RA.range(0, 100), traverseArray(log))() // it now prints 0 to 100
+```
+
+**Signature**
+
+```ts
+export declare const traverseArray: <A, B>(f: (a: A) => IO<B>) => (arr: readonly A[]) => IO<readonly B[]>
+```
+
+Added in v2.9.0
+
+## traverseArrayWithIndex
+
+**Signature**
+
+```ts
+export declare const traverseArrayWithIndex: <A, B>(
+  f: (index: number, a: A) => IO<B>
+) => (arr: readonly A[]) => IO<readonly B[]>
+```
+
+Added in v2.9.0
diff --git a/docs/modules/IOEither.ts.md b/docs/modules/IOEither.ts.md
index 65983fb1..b9d2ca7b 100644
--- a/docs/modules/IOEither.ts.md
+++ b/docs/modules/IOEither.ts.md
@@ -89,6 +89,12 @@ Added in v2.0.0
   - [bindTo](#bindto)
   - [bindW](#bindw)
   - [bracket](#bracket)
+  - [sequenceArray](#sequencearray)
+  - [sequenceSeqArray](#sequenceseqarray)
+  - [traverseArray](#traversearray)
+  - [traverseArrayWithIndex](#traversearraywithindex)
+  - [traverseSeqArray](#traverseseqarray)
+  - [traverseSeqArrayWithIndex](#traverseseqarraywithindex)
 
 ---
 
@@ -830,3 +836,71 @@ export declare const bracket: <E, A, B>(
 ```
 
 Added in v2.0.0
+
+## sequenceArray
+
+**Signature**
+
+```ts
+export declare const sequenceArray: <E, A>(arr: readonly IOEither<E, A>[]) => IOEither<E, readonly A[]>
+```
+
+Added in v2.9.0
+
+## sequenceSeqArray
+
+**Signature**
+
+```ts
+export declare const sequenceSeqArray: <E, A>(arr: readonly IOEither<E, A>[]) => IOEither<E, readonly A[]>
+```
+
+Added in v2.9.0
+
+## traverseArray
+
+**Signature**
+
+```ts
+export declare const traverseArray: <A, E, B>(
+  f: (a: A) => IOEither<E, B>
+) => (arr: readonly A[]) => IOEither<E, readonly B[]>
+```
+
+Added in v2.9.0
+
+## traverseArrayWithIndex
+
+**Signature**
+
+```ts
+export declare const traverseArrayWithIndex: <A, E, B>(
+  f: (index: number, a: A) => IOEither<E, B>
+) => (arr: readonly A[]) => IOEither<E, readonly B[]>
+```
+
+Added in v2.9.0
+
+## traverseSeqArray
+
+**Signature**
+
+```ts
+export declare const traverseSeqArray: <A, E, B>(
+  f: (a: A) => IOEither<E, B>
+) => (arr: readonly A[]) => IOEither<E, readonly B[]>
+```
+
+Added in v2.9.0
+
+## traverseSeqArrayWithIndex
+
+**Signature**
+
+```ts
+export declare const traverseSeqArrayWithIndex: <A, E, B>(
+  f: (index: number, a: A) => IOEither<E, B>
+) => (arr: readonly A[]) => IOEither<E, readonly B[]>
+```
+
+Added in v2.9.0
diff --git a/docs/modules/Option.ts.md b/docs/modules/Option.ts.md
index 8ce18c96..ed3f6ba6 100644
--- a/docs/modules/Option.ts.md
+++ b/docs/modules/Option.ts.md
@@ -120,6 +120,9 @@ Added in v2.0.0
   - [elem](#elem)
   - [exists](#exists)
   - [getRefinement](#getrefinement)
+  - [sequenceArray](#sequencearray)
+  - [traverseArray](#traversearray)
+  - [traverseArrayWithIndex](#traversearraywithindex)
 
 ---
 
@@ -539,8 +542,6 @@ Added in v2.0.0
 
 ## fromNullableK
 
-Returns a _smart constructor_ from a function that returns a nullable value.
-
 **Signature**
 
 ```ts
@@ -549,22 +550,6 @@ export declare function fromNullableK<A extends ReadonlyArray<unknown>, B>(
 ): (...a: A) => Option<NonNullable<B>>
 ```
 
-**Example**
-
-```ts
-import { fromNullableK, none, some } from 'fp-ts/Option'
-
-const f = (s: string): number | undefined => {
-  const n = parseFloat(s)
-  return isNaN(n) ? undefined : n
-}
-
-const g = fromNullableK(f)
-
-assert.deepStrictEqual(g('1'), some(1))
-assert.deepStrictEqual(g('a'), none)
-```
-
 Added in v2.9.0
 
 ## ~~mapNullable~~
@@ -1438,3 +1423,67 @@ export declare function getRefinement<A, B extends A>(getOption: (a: A) => Optio
 ```
 
 Added in v2.0.0
+
+## sequenceArray
+
+get an array of option and convert it to option of array
+
+this function have the same behavior of `A.sequence(O.option)` but it's optimized and perform better
+
+**Signature**
+
+```ts
+export declare const sequenceArray: <A>(arr: readonly Option<A>[]) => Option<readonly A[]>
+```
+
+**Example**
+
+```ts
+import * as A from 'fp-ts/Array'
+import { sequenceArray, some, none, fromPredicate } from 'fp-ts/Option'
+import { pipe } from 'fp-ts/function'
+
+const arr = A.range(0, 10)
+assert.deepStrictEqual(pipe(arr, A.map(some), sequenceArray), some(arr))
+assert.deepStrictEqual(pipe(arr, A.map(fromPredicate((x) => x > 8)), sequenceArray), none)
+```
+
+Added in v2.9.0
+
+## traverseArray
+
+Runs an action for every element in array and accumulates the results in option
+
+this function have the same behavior of `A.sequence(O.option)` but it's optimized and perform better
+
+**Signature**
+
+```ts
+export declare const traverseArray: <A, B>(f: (a: A) => Option<B>) => (arr: readonly A[]) => Option<readonly B[]>
+```
+
+**Example**
+
+```ts
+import * as A from 'fp-ts/Array'
+import { traverseArray, some, fromPredicate, none } from 'fp-ts/Option'
+import { pipe } from 'fp-ts/function'
+
+const arr = A.range(0, 10)
+assert.deepStrictEqual(pipe(arr, traverseArray(some)), some(arr))
+assert.deepStrictEqual(pipe(arr, traverseArray(fromPredicate((x) => x > 5))), none)
+```
+
+Added in v2.9.0
+
+## traverseArrayWithIndex
+
+**Signature**
+
+```ts
+export declare const traverseArrayWithIndex: <A, B>(
+  f: (index: number, a: A) => Option<B>
+) => (arr: readonly A[]) => Option<readonly B[]>
+```
+
+Added in v2.9.0
diff --git a/docs/modules/Reader.ts.md b/docs/modules/Reader.ts.md
index 35538186..48eff218 100644
--- a/docs/modules/Reader.ts.md
+++ b/docs/modules/Reader.ts.md
@@ -58,6 +58,9 @@ Added in v2.0.0
   - [bind](#bind)
   - [bindTo](#bindto)
   - [bindW](#bindw)
+  - [sequenceArray](#sequencearray)
+  - [traverseArray](#traversearray)
+  - [traverseArrayWithIndex](#traversearraywithindex)
 
 ---
 
@@ -477,3 +480,79 @@ export declare const bindW: <N extends string, A, Q, B>(
 ```
 
 Added in v2.8.0
+
+## sequenceArray
+
+this function have the same behavior of `A.sequence(R.reader)` but it's stack safe and optimized
+
+**Signature**
+
+```ts
+export declare const sequenceArray: <R, A>(arr: readonly Reader<R, A>[]) => Reader<R, readonly A[]>
+```
+
+**Example**
+
+```ts
+import * as RA from 'fp-ts/ReadonlyArray'
+import { sequenceArray, Reader } from 'fp-ts/Reader'
+import { pipe } from 'fp-ts/function'
+
+const add: (x: number) => Reader<{ value: number }, number> = (x) => (config) => x + config.value
+const arr = RA.range(0, 100)
+
+assert.deepStrictEqual(
+  pipe(arr, RA.map(add), sequenceArray)({ value: 3 }),
+  pipe(
+    arr,
+    RA.map((x) => x + 3)
+  )
+)
+```
+
+Added in v2.9.0
+
+## traverseArray
+
+this function have the same behavior of `A.traverse(R.reader)` but it's stack safe and optimized
+
+**Signature**
+
+```ts
+export declare const traverseArray: <R, A, B>(
+  f: (a: A) => Reader<R, B>
+) => (arr: readonly A[]) => Reader<R, readonly B[]>
+```
+
+**Example**
+
+```ts
+import * as RA from 'fp-ts/ReadonlyArray'
+import { traverseArray, Reader } from 'fp-ts/Reader'
+import { pipe } from 'fp-ts/function'
+
+const add: (x: number) => Reader<{ value: number }, number> = (x) => (config) => x + config.value
+const arr = RA.range(0, 100)
+
+assert.deepStrictEqual(
+  pipe(arr, traverseArray(add))({ value: 3 }),
+  pipe(
+    arr,
+    RA.map((x) => x + 3)
+  )
+)
+```
+
+Added in v2.9.0
+
+## traverseArrayWithIndex
+
+**Signature**
+
+```ts
+export declare const traverseArrayWithIndex: <R, A, B>(
+  f: (index: number, a: A) => Reader<R, B>
+) => (arr: readonly A[]) => Reader<R, readonly B[]>
+```
+
+Added in v2.9.0
diff --git a/docs/modules/ReaderEither.ts.md b/docs/modules/ReaderEither.ts.md
index 047b742c..60b82a20 100644
--- a/docs/modules/ReaderEither.ts.md
+++ b/docs/modules/ReaderEither.ts.md
@@ -81,6 +81,9 @@ Added in v2.0.0
   - [bind](#bind)
   - [bindTo](#bindto)
   - [bindW](#bindw)
+  - [sequenceArray](#sequencearray)
+  - [traverseArray](#traversearray)
+  - [traverseArrayWithIndex](#traversearraywithindex)
 
 ---
 
@@ -799,3 +802,37 @@ export declare const bindW: <N extends string, A, Q, D, B>(
 ```
 
 Added in v2.8.0
+
+## sequenceArray
+
+**Signature**
+
+```ts
+export declare const sequenceArray: <R, E, A>(arr: readonly ReaderEither<R, E, A>[]) => ReaderEither<R, E, readonly A[]>
+```
+
+Added in v2.9.0
+
+## traverseArray
+
+**Signature**
+
+```ts
+export declare const traverseArray: <R, E, A, B>(
+  f: (a: A) => ReaderEither<R, E, B>
+) => (arr: readonly A[]) => ReaderEither<R, E, readonly B[]>
+```
+
+Added in v2.9.0
+
+## traverseArrayWithIndex
+
+**Signature**
+
+```ts
+export declare const traverseArrayWithIndex: <R, E, A, B>(
+  f: (index: number, a: A) => ReaderEither<R, E, B>
+) => (arr: readonly A[]) => ReaderEither<R, E, readonly B[]>
+```
+
+Added in v2.9.0
diff --git a/docs/modules/ReaderTask.ts.md b/docs/modules/ReaderTask.ts.md
index 6a146dee..f686c2ce 100644
--- a/docs/modules/ReaderTask.ts.md
+++ b/docs/modules/ReaderTask.ts.md
@@ -57,6 +57,9 @@ Added in v2.3.0
   - [bindTo](#bindto)
   - [bindW](#bindw)
   - [run](#run)
+  - [sequenceArray](#sequencearray)
+  - [traverseArray](#traversearray)
+  - [traverseArrayWithIndex](#traversearraywithindex)
 
 ---
 
@@ -491,3 +494,37 @@ export declare function run<R, A>(ma: ReaderTask<R, A>, r: R): Promise<A>
 ```
 
 Added in v2.4.0
+
+## sequenceArray
+
+**Signature**
+
+```ts
+export declare const sequenceArray: <R, A>(arr: readonly ReaderTask<R, A>[]) => ReaderTask<R, readonly A[]>
+```
+
+Added in v2.9.0
+
+## traverseArray
+
+**Signature**
+
+```ts
+export declare const traverseArray: <R, A, B>(
+  f: (a: A) => ReaderTask<R, B>
+) => (arr: readonly A[]) => ReaderTask<R, readonly B[]>
+```
+
+Added in v2.9.0
+
+## traverseArrayWithIndex
+
+**Signature**
+
+```ts
+export declare const traverseArrayWithIndex: <R, A, B>(
+  f: (index: number, a: A) => ReaderTask<R, B>
+) => (arr: readonly A[]) => ReaderTask<R, readonly B[]>
+```
+
+Added in v2.9.0
diff --git a/docs/modules/ReaderTaskEither.ts.md b/docs/modules/ReaderTaskEither.ts.md
index f9c41e2d..91e5712d 100644
--- a/docs/modules/ReaderTaskEither.ts.md
+++ b/docs/modules/ReaderTaskEither.ts.md
@@ -102,6 +102,12 @@ Added in v2.0.0
   - [bindW](#bindw)
   - [bracket](#bracket)
   - [run](#run)
+  - [sequenceArray](#sequencearray)
+  - [sequenceSeqArray](#sequenceseqarray)
+  - [traverseArray](#traversearray)
+  - [traverseArrayWithIndex](#traversearraywithindex)
+  - [traverseSeqArray](#traverseseqarray)
+  - [traverseSeqArrayWithIndex](#traverseseqarraywithindex)
 
 ---
 
@@ -1054,3 +1060,75 @@ export declare function run<R, E, A>(ma: ReaderTaskEither<R, E, A>, r: R): Promi
 ```
 
 Added in v2.0.0
+
+## sequenceArray
+
+**Signature**
+
+```ts
+export declare const sequenceArray: <R, E, A>(
+  arr: readonly ReaderTaskEither<R, E, A>[]
+) => ReaderTaskEither<R, E, readonly A[]>
+```
+
+Added in v2.9.0
+
+## sequenceSeqArray
+
+**Signature**
+
+```ts
+export declare const sequenceSeqArray: <R, E, A>(
+  arr: readonly ReaderTaskEither<R, E, A>[]
+) => ReaderTaskEither<R, E, readonly A[]>
+```
+
+Added in v2.9.0
+
+## traverseArray
+
+**Signature**
+
+```ts
+export declare const traverseArray: <R, E, A, B>(
+  f: (a: A) => ReaderTaskEither<R, E, B>
+) => (arr: readonly A[]) => ReaderTaskEither<R, E, readonly B[]>
+```
+
+Added in v2.9.0
+
+## traverseArrayWithIndex
+
+**Signature**
+
+```ts
+export declare const traverseArrayWithIndex: <R, E, A, B>(
+  f: (index: number, a: A) => ReaderTaskEither<R, E, B>
+) => (arr: readonly A[]) => ReaderTaskEither<R, E, readonly B[]>
+```
+
+Added in v2.9.0
+
+## traverseSeqArray
+
+**Signature**
+
+```ts
+export declare const traverseSeqArray: <R, E, A, B>(
+  f: (a: A) => ReaderTaskEither<R, E, B>
+) => (arr: readonly A[]) => ReaderTaskEither<R, E, readonly B[]>
+```
+
+Added in v2.9.0
+
+## traverseSeqArrayWithIndex
+
+**Signature**
+
+```ts
+export declare const traverseSeqArrayWithIndex: <R, E, A, B>(
+  f: (index: number, a: A) => ReaderTaskEither<R, E, B>
+) => (arr: readonly A[]) => ReaderTaskEither<R, E, readonly B[]>
+```
+
+Added in v2.9.0
diff --git a/docs/modules/ReadonlyArray.ts.md b/docs/modules/ReadonlyArray.ts.md
index e4251318..8ebc1006 100644
--- a/docs/modules/ReadonlyArray.ts.md
+++ b/docs/modules/ReadonlyArray.ts.md
@@ -479,6 +479,8 @@ Added in v2.5.0
 
 ## sequence
 
+**for optimized and stack safe version check the data types `sequenceArray` function**
+
 **Signature**
 
 ```ts
@@ -489,6 +491,8 @@ Added in v2.6.3
 
 ## traverse
 
+**for optimized and stack safe version check the data types `traverseArray` function**
+
 **Signature**
 
 ```ts
@@ -501,6 +505,8 @@ Added in v2.6.3
 
 ## traverseWithIndex
 
+**for optimized and stack safe version check the data types `traverseArrayWithIndex` function**
+
 **Signature**
 
 ```ts
diff --git a/docs/modules/State.ts.md b/docs/modules/State.ts.md
index bb94c053..59dcdf2a 100644
--- a/docs/modules/State.ts.md
+++ b/docs/modules/State.ts.md
@@ -45,6 +45,9 @@ Added in v2.0.0
   - [bindTo](#bindto)
   - [evaluate](#evaluate)
   - [execute](#execute)
+  - [sequenceArray](#sequencearray)
+  - [traverseArray](#traversearray)
+  - [traverseArrayWithIndex](#traversearraywithindex)
   - [~~evalState~~](#evalstate)
   - [~~execState~~](#execstate)
 
@@ -352,6 +355,68 @@ export declare const execute: <S>(s: S) => <A>(ma: State<S, A>) => S
 
 Added in v2.8.0
 
+## sequenceArray
+
+This function has the same behavior of `A.sequence(S.State)` but it's stack safe and optimized
+
+**Signature**
+
+```ts
+export declare const sequenceArray: <S, A>(arr: readonly State<S, A>[]) => State<S, readonly A[]>
+```
+
+**Example**
+
+```ts
+import * as RA from 'fp-ts/ReadonlyArray'
+import { sequenceArray, State } from 'fp-ts/State'
+import { pipe, tuple } from 'fp-ts/function'
+
+const add = (n: number): State<number, number> => (s: number) => tuple(n, n + s)
+const arr = RA.range(0, 100)
+
+assert.deepStrictEqual(pipe(arr, RA.map(add), sequenceArray)(0), [arr, arr.reduce((p, c) => p + c, 0)])
+```
+
+Added in v2.9
+
+## traverseArray
+
+This function has the same behavior of `A.traverse(S.State)` but it's stack safe and optimized
+
+**Signature**
+
+```ts
+export declare const traverseArray: <A, S, B>(f: (a: A) => State<S, B>) => (arr: readonly A[]) => State<S, readonly B[]>
+```
+
+**Example**
+
+```ts
+import * as RA from 'fp-ts/ReadonlyArray'
+import { traverseArray, State } from 'fp-ts/State'
+import { pipe, tuple } from 'fp-ts/function'
+
+const add = (n: number): State<number, number> => (s: number) => tuple(n, n + s)
+const arr = RA.range(0, 100)
+
+assert.deepStrictEqual(pipe(arr, traverseArray(add))(0), [arr, arr.reduce((p, c) => p + c, 0)])
+```
+
+Added in v2.9
+
+## traverseArrayWithIndex
+
+**Signature**
+
+```ts
+export declare const traverseArrayWithIndex: <A, S, B>(
+  f: (index: number, a: A) => State<S, B>
+) => (arr: readonly A[]) => State<S, readonly B[]>
+```
+
+Added in v2.9.0
+
 ## ~~evalState~~
 
 Use `evaluate` instead
diff --git a/docs/modules/StateReaderTaskEither.ts.md b/docs/modules/StateReaderTaskEither.ts.md
index 21bbc0ce..c87850bb 100644
--- a/docs/modules/StateReaderTaskEither.ts.md
+++ b/docs/modules/StateReaderTaskEither.ts.md
@@ -95,6 +95,9 @@ Added in v2.0.0
   - [evaluate](#evaluate)
   - [execute](#execute)
   - [run](#run)
+  - [sequenceArray](#sequencearray)
+  - [traverseArray](#traversearray)
+  - [traverseArrayWithIndex](#traversearraywithindex)
   - [~~evalState~~](#evalstate)
   - [~~execState~~](#execstate)
 
@@ -992,6 +995,42 @@ export declare function run<S, R, E, A>(ma: StateReaderTaskEither<S, R, E, A>, s
 
 Added in v2.0.0
 
+## sequenceArray
+
+**Signature**
+
+```ts
+export declare const sequenceArray: <S, R, E, A>(
+  arr: readonly StateReaderTaskEither<S, R, E, A>[]
+) => StateReaderTaskEither<S, R, E, readonly A[]>
+```
+
+Added in v2.9.0
+
+## traverseArray
+
+**Signature**
+
+```ts
+export declare const traverseArray: <S, R, E, A, B>(
+  f: (a: A) => StateReaderTaskEither<S, R, E, B>
+) => (arr: readonly A[]) => StateReaderTaskEither<S, R, E, readonly B[]>
+```
+
+Added in v2.9.0
+
+## traverseArrayWithIndex
+
+**Signature**
+
+```ts
+export declare const traverseArrayWithIndex: <S, R, E, A, B>(
+  f: (index: number, a: A) => StateReaderTaskEither<S, R, E, B>
+) => (arr: readonly A[]) => StateReaderTaskEither<S, R, E, readonly B[]>
+```
+
+Added in v2.9.0
+
 ## ~~evalState~~
 
 Use `evaluate` instead
diff --git a/docs/modules/Task.ts.md b/docs/modules/Task.ts.md
index 5bd78d57..09ca6bea 100644
--- a/docs/modules/Task.ts.md
+++ b/docs/modules/Task.ts.md
@@ -59,6 +59,12 @@ Added in v2.0.0
   - [bind](#bind)
   - [bindTo](#bindto)
   - [never](#never)
+  - [sequenceArray](#sequencearray)
+  - [sequenceSeqArray](#sequenceseqarray)
+  - [traverseArray](#traversearray)
+  - [traverseArrayWithIndex](#traversearraywithindex)
+  - [traverseSeqArray](#traverseseqarray)
+  - [traverseSeqArrayWithIndex](#traverseseqarraywithindex)
 
 ---
 
@@ -461,3 +467,120 @@ export declare const never: Task<never>
 ```
 
 Added in v2.0.0
+
+## sequenceArray
+
+this function works like `Promise.all` it will get an array of tasks and return a task of array.
+
+this function have the same behavior of `A.sequence(T.task)` but it's stack safe.
+
+> **This function run all task in parallel for sequential use `sequenceSeqArray` **
+
+**Signature**
+
+```ts
+export declare const sequenceArray: <A>(arr: readonly Task<A>[]) => Task<readonly A[]>
+```
+
+**Example**
+
+```ts
+import * as RA from 'fp-ts/ReadonlyArray'
+import { pipe } from 'fp-ts/function'
+import { of, sequenceArray } from 'fp-ts/Task'
+
+async function test() {
+  const arr = RA.range(1, 10)
+  assert.deepStrictEqual(await pipe(arr, RA.map(of), sequenceArray)(), arr)
+}
+
+test()
+```
+
+Added in v2.9.0
+
+## sequenceSeqArray
+
+run tasks in array sequential and give a task of array
+
+this function have the same behavior of `A.sequence(T.taskSeq)` but it's stack safe.
+
+> **This function run all task sequentially for parallel use `sequenceArray` **
+
+**Signature**
+
+```ts
+export declare const sequenceSeqArray: <A>(arr: readonly Task<A>[]) => Task<readonly A[]>
+```
+
+Added in v2.9.0
+
+## traverseArray
+
+this function map array to task using provided function and transform it to a task of array.
+
+this function have the same behavior of `A.traverse(T.task)` but it's stack safe.
+
+> **This function run all task in parallel for sequential use `traverseSeqArray` **
+
+**Signature**
+
+```ts
+export declare const traverseArray: <A, B>(f: (a: A) => Task<B>) => (arr: readonly A[]) => Task<readonly B[]>
+```
+
+**Example**
+
+```ts
+import { range } from 'fp-ts/ReadonlyArray'
+import { pipe } from 'fp-ts/function'
+import { of, traverseArray } from 'fp-ts/Task'
+async function test() {
+  const arr = range(0, 10)
+  assert.deepStrictEqual(await pipe(arr, traverseArray(of))(), arr)
+}
+
+test()
+```
+
+Added in v2.9.0
+
+## traverseArrayWithIndex
+
+**Signature**
+
+```ts
+export declare const traverseArrayWithIndex: <A, B>(
+  f: (index: number, a: A) => Task<B>
+) => (arr: readonly A[]) => Task<readonly B[]>
+```
+
+Added in v2.9.0
+
+## traverseSeqArray
+
+runs an action for every element in array then run task sequential, and accumulates the results in the array.
+
+this function have the same behavior of `A.traverse(T.taskSeq)` but it's stack safe.
+
+> **This function run all task sequentially for parallel use `traverseArray` **
+
+**Signature**
+
+```ts
+export declare const traverseSeqArray: <A, B>(f: (a: A) => Task<B>) => (arr: readonly A[]) => Task<readonly B[]>
+```
+
+Added in v2.9.0
+
+## traverseSeqArrayWithIndex
+
+**Signature**
+
+```ts
+export declare const traverseSeqArrayWithIndex: <A, B>(
+  f: (index: number, a: A) => Task<B>
+) => (arr: readonly A[]) => Task<readonly B[]>
+```
+
+Added in v2.9.0
diff --git a/docs/modules/TaskEither.ts.md b/docs/modules/TaskEither.ts.md
index 98a876bc..77ce8de8 100644
--- a/docs/modules/TaskEither.ts.md
+++ b/docs/modules/TaskEither.ts.md
@@ -98,7 +98,13 @@ Added in v2.0.0
   - [bindTo](#bindto)
   - [bindW](#bindw)
   - [bracket](#bracket)
+  - [sequenceArray](#sequencearray)
+  - [sequenceSeqArray](#sequenceseqarray)
   - [taskify](#taskify)
+  - [traverseArray](#traversearray)
+  - [traverseArrayWithIndex](#traversearraywithindex)
+  - [traverseSeqArray](#traverseseqarray)
+  - [traverseSeqArrayWithIndex](#traverseseqarraywithindex)
 
 ---
 
@@ -988,6 +994,65 @@ export declare const bracket: <E, A, B>(
 
 Added in v2.0.0
 
+## sequenceArray
+
+this function have the same behavior of `A.sequence(TE.taskEither)` but it's stack safe and perform better
+
+_this function run all tasks in parallel and does not bail out, for sequential version use `sequenceSeqArray`_
+
+**Signature**
+
+```ts
+export declare const sequenceArray: <A, E>(arr: readonly TaskEither<E, A>[]) => TaskEither<E, readonly A[]>
+```
+
+**Example**
+
+```ts
+import * as TE from 'fp-ts/TaskEither'
+import * as A from 'fp-ts/Array'
+import { right } from 'fp-ts/Either'
+import { pipe } from 'fp-ts/function'
+
+const PostRepo = {
+  findById: (id: number) => TE.of({ id, title: '' }),
+}
+
+const findAllPosts = (ids: number[]) => pipe(ids, A.map(PostRepo.findById), TE.sequenceArray)
+
+async function test() {
+  const ids = A.range(0, 10)
+
+  assert.deepStrictEqual(
+    await findAllPosts(ids)(),
+    right(
+      pipe(
+        ids,
+        A.map((id) => ({ id, title: '' }))
+      )
+    )
+  )
+}
+
+test()
+```
+
+Added in v2.9.0
+
+## sequenceSeqArray
+
+this function have the same behavior of `A.sequence(TE.taskEitherSeq)` but it's stack safe and perform better
+
+_this function run all tasks in sequential order and bails out on left side of either, for parallel version use `sequenceArray`_
+
+**Signature**
+
+```ts
+export declare const sequenceSeqArray: <A, E>(arr: readonly TaskEither<E, A>[]) => TaskEither<E, readonly A[]>
+```
+
+Added in v2.9.0
+
 ## taskify
 
 Convert a node style callback function to one returning a `TaskEither`
@@ -1039,3 +1104,90 @@ assert.strictEqual(stat.length, 0)
 ```
 
 Added in v2.0.0
+
+## traverseArray
+
+this function have the same behavior of `A.traverse(TE.taskEither)` but it's stack safe and perform better
+
+_this function run all tasks in parallel and does not bail out, for sequential version use `traverseSeqArray`_
+
+**Signature**
+
+```ts
+export declare const traverseArray: <A, B, E>(
+  f: (a: A) => TaskEither<E, B>
+) => (arr: readonly A[]) => TaskEither<E, readonly B[]>
+```
+
+**Example**
+
+```ts
+import * as TE from 'fp-ts/TaskEither'
+import * as A from 'fp-ts/Array'
+import { right } from 'fp-ts/Either'
+import { pipe } from 'fp-ts/function'
+
+const PostRepo = {
+  findById: (id: number) => TE.of({ id, title: '' }),
+}
+
+const findAllPosts = (ids: number[]) => pipe(ids, TE.traverseArray(PostRepo.findById))
+
+async function test() {
+  const ids = A.range(0, 10)
+
+  assert.deepStrictEqual(
+    await findAllPosts(ids)(),
+    right(
+      pipe(
+        ids,
+        A.map((id) => ({ id, title: '' }))
+      )
+    )
+  )
+}
+
+test()
+```
+
+Added in v2.9.0
+
+## traverseArrayWithIndex
+
+**Signature**
+
+```ts
+export declare const traverseArrayWithIndex: <A, B, E>(
+  f: (index: number, a: A) => TaskEither<E, B>
+) => (arr: readonly A[]) => TaskEither<E, readonly B[]>
+```
+
+Added in v2.9.0
+
+## traverseSeqArray
+
+this function have the same behavior of `A.traverse(TE.taskEitherSeq)` but it's stack safe and perform better
+
+_this function run all tasks in sequential order and bails out on left side of either, for parallel version use `traverseArray`_
+
+**Signature**
+
+```ts
+export declare const traverseSeqArray: <A, B, E>(
+  f: (a: A) => TaskEither<E, B>
+) => (arr: readonly A[]) => TaskEither<E, readonly B[]>
+```
+
+Added in v2.9.0
+
+## traverseSeqArrayWithIndex
+
+**Signature**
+
+```ts
+export declare const traverseSeqArrayWithIndex: <A, B, E>(
+  f: (index: number, a: A) => TaskEither<E, B>
+) => (arr: readonly A[]) => TaskEither<E, readonly B[]>
+```
+
+Added in v2.9.0
diff --git a/perf/Either/sequenceArray.ts b/perf/Either/sequenceArray.ts
new file mode 100644
index 00000000..2fec77e5
--- /dev/null
+++ b/perf/Either/sequenceArray.ts
@@ -0,0 +1,32 @@
+import * as Benchmark from 'benchmark'
+import * as A from '../../src/Array'
+import * as E from '../../src/Either'
+import { pipe } from '../../src/function'
+
+/*
+for an array with size 1000
+A.sequence(E.either) x 311 ops/sec ±9.97% (59 runs sampled)
+E.sequenceArray x 92,649 ops/sec ±9.29% (66 runs sampled)
+Fastest is E.sequenceA
+*/
+
+const suite = new Benchmark.Suite()
+
+const arrE = pipe(A.range(0, 1000), A.map(E.right))
+
+suite
+  .add('A.sequence(E.either)', function () {
+    pipe(arrE, A.sequence(E.either))
+  })
+  .add('E.sequenceArray', function () {
+    pipe(arrE, E.sequenceArray)
+  })
+  .on('cycle', function (event: any) {
+    // tslint:disable-next-line: no-console
+    console.log(String(event.target))
+  })
+  .on('complete', function (this: any) {
+    // tslint:disable-next-line: no-console
+    console.log('Fastest is ' + this.filter('fastest').map('name'))
+  })
+  .run({ async: true })
diff --git a/perf/IO/sequenceArray.ts b/perf/IO/sequenceArray.ts
new file mode 100644
index 00000000..e8201ed2
--- /dev/null
+++ b/perf/IO/sequenceArray.ts
@@ -0,0 +1,32 @@
+import * as Benchmark from 'benchmark'
+import * as A from '../../src/Array'
+import * as IO from '../../src/IO'
+import { pipe } from '../../src/function'
+
+/*
+for an array with size 1000
+A.sequence(IO.io) x 20,063 ops/sec ±2.88% (84 runs sampled)
+IO.sequenceArray x 31,780,061 ops/sec ±4.52% (85 runs sampled)
+Fastest is IO.sequenceA
+*/
+
+const suite = new Benchmark.Suite()
+
+const arrIO = pipe(A.range(0, 1000), A.map(IO.of))
+
+suite
+  .add('A.sequence(IO.io)', function () {
+    pipe(arrIO, A.sequence(IO.io))
+  })
+  .add('IO.sequenceArray', function () {
+    pipe(arrIO, IO.sequenceArray)
+  })
+  .on('cycle', function (event: any) {
+    // tslint:disable-next-line: no-console
+    console.log(String(event.target))
+  })
+  .on('complete', function (this: any) {
+    // tslint:disable-next-line: no-console
+    console.log('Fastest is ' + this.filter('fastest').map('name'))
+  })
+  .run({ async: true })
diff --git a/perf/Option/sequenceArray.ts b/perf/Option/sequenceArray.ts
new file mode 100644
index 00000000..67c2e1fd
--- /dev/null
+++ b/perf/Option/sequenceArray.ts
@@ -0,0 +1,32 @@
+import * as Benchmark from 'benchmark'
+import * as A from '../../src/Array'
+import * as O from '../../src/Option'
+import { pipe } from '../../src/function'
+
+/*
+for an array with size 1000
+A.sequence(O.option) x 1,140 ops/sec ±0.23% (90 runs sampled)
+O.sequenceArray x 77,823 ops/sec ±2.87% (87 runs sampled)
+Fastest is O.sequenceA
+*/
+
+const suite = new Benchmark.Suite()
+
+const arr = A.range(0, 1000)
+
+suite
+  .add('A.sequence(O.option)', function () {
+    return pipe(arr, A.map(O.some), A.sequence(O.option))
+  })
+  .add('O.sequenceArray', function () {
+    return pipe(arr, A.map(O.some), O.sequenceArray)
+  })
+  .on('cycle', function (event: any) {
+    // tslint:disable-next-line: no-console
+    console.log(String(event.target))
+  })
+  .on('complete', function (this: any) {
+    // tslint:disable-next-line: no-console
+    console.log('Fastest is ' + this.filter('fastest').map('name'))
+  })
+  .run({ async: true })
diff --git a/perf/Task/sequenceArray.ts b/perf/Task/sequenceArray.ts
new file mode 100644
index 00000000..36a8b0e3
--- /dev/null
+++ b/perf/Task/sequenceArray.ts
@@ -0,0 +1,40 @@
+import * as Benchmark from 'benchmark'
+import * as A from '../../src/Array'
+import * as T from '../../src/Task'
+import { pipe } from '../../src/function'
+
+/*
+for an array with size 1000
+A.sequence(T.task) x 534 ops/sec ±10.52% (64 runs sampled)
+T.sequenceArray x 4,237 ops/sec ±7.82% (71 runs sampled)
+Promise.all x 4,863 ops/sec ±7.57% (74 runs sampled)
+Fastest is Promise.allA
+*/
+
+const suite = new Benchmark.Suite()
+
+const arr = A.range(0, 1000)
+
+suite
+  .add('A.sequence(T.task)', function () {
+    return pipe(arr, A.map(T.of), A.sequence(T.task))()
+  })
+  .add('T.sequenceArray', function () {
+    return pipe(arr, A.map(T.of), T.sequenceArray)()
+  })
+  .add('Promise.all', function () {
+    return pipe(
+      arr,
+      A.map((x) => Promise.resolve(x)),
+      (x) => Promise.all(x)
+    )
+  })
+  .on('cycle', function (event: any) {
+    // tslint:disable-next-line: no-console
+    console.log(String(event.target))
+  })
+  .on('complete', function (this: any) {
+    // tslint:disable-next-line: no-console
+    console.log('Fastest is ' + this.filter('fastest').map('name'))
+  })
+  .run({ async: true })
diff --git a/src/Array.ts b/src/Array.ts
index c1cff16f..b577b46b 100644
--- a/src/Array.ts
+++ b/src/Array.ts
@@ -1262,18 +1262,21 @@ export const reduceRightWithIndex: <A, B>(b: B, f: (i: number, a: A, b: B) => B)
   RA.reduceRightWithIndex
 
 /**
+ * **for optimized and stack safe version check the data types `traverseArray` function**
  * @category Traversable
  * @since 2.6.3
  */
 export const traverse: PipeableTraverse1<URI> = RA.traverse as any
 
 /**
+ * **for optimized and stack safe version check the data types `sequenceArray` function**
  * @category Traversable
  * @since 2.6.3
  */
 export const sequence: Traversable1<URI>['sequence'] = RA.sequence as any
 
 /**
+ * **for optimized and stack safe version check the data types `traverseArrayWithIndex` function**
  * @category TraversableWithIndex
  * @since 2.6.3
  */
diff --git a/src/Either.ts b/src/Either.ts
index cb28c876..ec5912df 100644
--- a/src/Either.ts
+++ b/src/Either.ts
@@ -1370,3 +1370,83 @@ export const apS: <A, N extends string, E, B>(
   name: Exclude<N, keyof A>,
   fb: Either<E, B>
 ) => (fa: Either<E, A>) => Either<E, { [K in keyof A | N]: K extends keyof A ? A[K] : B }> = apSW
+
+// -------------------------------------------------------------------------------------
+// array utils
+// -------------------------------------------------------------------------------------
+
+/**
+ *
+ * @since 2.9.0
+ */
+export const traverseArrayWithIndex = <E, A, B>(f: (index: number, a: A) => Either<E, B>) => (
+  arr: ReadonlyArray<A>
+): Either<E, ReadonlyArray<B>> => {
+  // tslint:disable-next-line: readonly-array
+  const result = []
+  for (let i = 0; i < arr.length; i++) {
+    const e = f(i, arr[i])
+    if (e._tag === 'Left') {
+      return e
+    }
+    result.push(e.right)
+  }
+  return right(result)
+}
+
+/**
+ * map an array using provided function to Either then transform to Either of the array
+ * this function have the same behavior of `A.traverse(E.either)` but it's optimized and perform better
+ *
+ * @example
+ *
+ *
+ * import { traverseArray, left, right, fromPredicate } from 'fp-ts/Either'
+ * import { pipe } from 'fp-ts/function'
+ * import * as A from 'fp-ts/Array'
+ *
+ * const arr = A.range(0, 10)
+ * assert.deepStrictEqual(
+ *   pipe(
+ *     arr,
+ *     traverseArray((x) => right(x))
+ *   ),
+ *   right(arr)
+ * )
+ * assert.deepStrictEqual(
+ *   pipe(
+ *     arr,
+ *     traverseArray(
+ *       fromPredicate(
+ *         (x) => x > 5,
+ *         () => 'a'
+ *       )
+ *     )
+ *   ),
+ *   left('a')
+ * )
+ * @since 2.9.0
+ */
+export const traverseArray: <E, A, B>(
+  f: (a: A) => Either<E, B>
+) => (arr: ReadonlyArray<A>) => Either<E, ReadonlyArray<B>> = (f) => traverseArrayWithIndex((_, a) => f(a))
+
+/**
+ * convert an array of either to an either of array
+ * this function have the same behavior of `A.sequence(E.either)` but it's optimized and perform better
+ *
+ * @example
+ *
+ * import { sequenceArray, left, right } from 'fp-ts/Either'
+ * import { pipe } from 'fp-ts/function'
+ * import * as A from 'fp-ts/Array'
+ *
+ * const arr = A.range(0, 10)
+ * assert.deepStrictEqual(pipe(arr, A.map(right), sequenceArray), right(arr))
+ * assert.deepStrictEqual(pipe(arr, A.map(right), A.cons(left('Error')), sequenceArray), left('Error'))
+ *
+ * @since 2.9.0
+ */
+export const sequenceArray: <E, A>(arr: ReadonlyArray<Either<E, A>>) => Either<E, ReadonlyArray<A>> = traverseArray(
+  identity
+)
diff --git a/src/IO.ts b/src/IO.ts
index aed00478..93cfdba2 100644
--- a/src/IO.ts
+++ b/src/IO.ts
@@ -298,3 +298,54 @@ export const apS = <A, N extends string, B>(
     map((a) => (b: B) => bind_(a, name, b)),
     ap(fb)
   )
+
+// -------------------------------------------------------------------------------------
+// array utils
+// -------------------------------------------------------------------------------------
+
+/**
+ * @since 2.9.0
+ */
+export const traverseArrayWithIndex: <A, B>(
+  f: (index: number, a: A) => IO<B>
+) => (arr: ReadonlyArray<A>) => IO<ReadonlyArray<B>> = (f) => (arr) => () => arr.map((a, i) => f(i, a)())
+
+/**
+ * runs an action for every element in array, and accumulates the results IO in the array.
+ *
+ * this function have the same behavior of `A.traverse(IO.io)` but it's stack safe
+ *
+ * ```ts
+ * import * as RA from 'fp-ts/ReadonlyArray'
+ * import { traverseArray, IO } from 'fp-ts/IO'
+ * import { pipe } from 'fp-ts/function'
+ *
+ * const log: <A>(x: A) => IO<void> = (x) => () => console.log(x)
+ *
+ * pipe(RA.range(0, 100), traverseArray(log))() // it now prints 0 to 100
+ * ```
+ *
+ * @since 2.9.0
+ */
+export const traverseArray: <A, B>(f: (a: A) => IO<B>) => (arr: ReadonlyArray<A>) => IO<ReadonlyArray<B>> = (f) =>
+  traverseArrayWithIndex((_, a) => f(a))
+
+/**
+ * transform Array of IO to IO of Array
+ *
+ * this function have the same behavior of `A.sequence(IO.io)` but it's stack safe
+ *
+ * ```ts
+ * import * as RA from 'fp-ts/ReadonlyArray'
+ * import { sequenceArray, IO } from 'fp-ts/IO'
+ * import { pipe } from 'fp-ts/function'
+ *
+ * const log: <A>(x: A) => IO<void> = (x) => () => console.log(x)
+ *
+ * pipe(RA.range(0, 100), RA.map(log), sequenceA)() // it now prints 0 to 100
+ * ```
+ *
+ *
+ * @since 2.9.0
+ */
+export const sequenceArray: <A>(arr: ReadonlyArray<IO<A>>) => IO<ReadonlyArray<A>> = traverseArray(identity)
diff --git a/src/IOEither.ts b/src/IOEither.ts
index 5280df20..7ebf23ce 100644
--- a/src/IOEither.ts
+++ b/src/IOEither.ts
@@ -732,3 +732,62 @@ export const apS: <A, N extends string, E, B>(
   name: Exclude<N, keyof A>,
   fb: IOEither<E, B>
 ) => (fa: IOEither<E, A>) => IOEither<E, { [K in keyof A | N]: K extends keyof A ? A[K] : B }> = apSW
+
+// -------------------------------------------------------------------------------------
+// array utils
+// -------------------------------------------------------------------------------------
+
+/**
+ * @since 2.9.0
+ */
+export const traverseArrayWithIndex: <A, E, B>(
+  f: (index: number, a: A) => IOEither<E, B>
+) => (arr: ReadonlyArray<A>) => IOEither<E, ReadonlyArray<B>> = (f) =>
+  flow(I.traverseArrayWithIndex(f), I.map(E.sequenceArray))
+
+/**
+ * @since 2.9.0
+ */
+export const traverseArray: <A, E, B>(
+  f: (a: A) => IOEither<E, B>
+) => (arr: ReadonlyArray<A>) => IOEither<E, ReadonlyArray<B>> = (f) => traverseArrayWithIndex((_, a) => f(a))
+
+/**
+ *
+ * @since 2.9.0
+ */
+export const sequenceArray: <E, A>(arr: ReadonlyArray<IOEither<E, A>>) => IOEither<E, ReadonlyArray<A>> = traverseArray(
+  identity
+)
+
+/**
+ * @since 2.9.0
+ */
+export const traverseSeqArrayWithIndex: <A, E, B>(
+  f: (index: number, a: A) => IOEither<E, B>
+) => (arr: ReadonlyArray<A>) => IOEither<E, ReadonlyArray<B>> = (f) => (arr) => () => {
+  // tslint:disable-next-line: readonly-array
+  const result = []
+  for (let i = 0; i < arr.length; i++) {
+    const b = f(i, arr[i])()
+    if (E.isLeft(b)) {
+      return b
+    }
+    result.push(b.right)
+  }
+  return E.right(result)
+}
+
+/**
+ * @since 2.9.0
+ */
+export const traverseSeqArray: <A, E, B>(
+  f: (a: A) => IOEither<E, B>
+) => (arr: ReadonlyArray<A>) => IOEither<E, ReadonlyArray<B>> = (f) => traverseSeqArrayWithIndex((_, a) => f(a))
+
+/**
+ * @since 2.9.0
+ */
+export const sequenceSeqArray: <E, A>(
+  arr: ReadonlyArray<IOEither<E, A>>
+) => IOEither<E, ReadonlyArray<A>> = traverseSeqArray(identity)
diff --git a/src/Option.ts b/src/Option.ts
index 669f1b47..89c75e2c 100644
--- a/src/Option.ts
+++ b/src/Option.ts
@@ -355,21 +355,6 @@ export const getOrElse: <A>(onNone: Lazy<A>) => (ma: Option<A>) => A = getOrElse
 // -------------------------------------------------------------------------------------
 
 /**
- * Returns a *smart constructor* from a function that returns a nullable value.
- *
- * @example
- * import { fromNullableK, none, some } from 'fp-ts/Option'
- *
- * const f = (s: string): number | undefined => {
- *   const n = parseFloat(s)
- *   return isNaN(n) ? undefined : n
- * }
- *
- * const g = fromNullableK(f)
- *
- * assert.deepStrictEqual(g('1'), some(1))
- * assert.deepStrictEqual(g('a'), none)
- *
  * @category combinators
  * @since 2.9.0
  */
@@ -1280,3 +1265,66 @@ export const apS = <A, N extends string, B>(
     map((a) => (b: B) => bind_(a, name, b)),
     ap(fb)
   )
+
+// -------------------------------------------------------------------------------------
+// array utils
+// -------------------------------------------------------------------------------------
+
+/**
+ *
+ * @since 2.9.0
+ */
+export const traverseArrayWithIndex = <A, B>(f: (index: number, a: A) => Option<B>) => (
+  arr: ReadonlyArray<A>
+): Option<ReadonlyArray<B>> => {
+  // tslint:disable-next-line: readonly-array
+  const result = []
+  for (let i = 0; i < arr.length; i++) {
+    const b = f(i, arr[i])
+    if (isNone(b)) {
+      return none
+    }
+    result.push(b.value)
+  }
+  return some(result)
+}
+
+/**
+ * Runs an action for every element in array and accumulates the results in option
+ *
+ * this function have the same behavior of `A.sequence(O.option)` but it's optimized and perform better
+ *
+ * @example
+ *
+ * import * as A from 'fp-ts/Array'
+ * import { traverseArray, some, fromPredicate, none } from 'fp-ts/Option'
+ * import { pipe } from 'fp-ts/function'
+ *
+ * const arr = A.range(0, 10)
+ * assert.deepStrictEqual(pipe(arr, traverseArray(some)), some(arr))
+ * assert.deepStrictEqual(pipe(arr, traverseArray(fromPredicate((x) => x > 5))), none)
+ *
+ * @since 2.9.0
+ */
+export const traverseArray: <A, B>(f: (a: A) => Option<B>) => (arr: ReadonlyArray<A>) => Option<ReadonlyArray<B>> = (
+  f
+) => traverseArrayWithIndex((_, a) => f(a))
+
+/**
+ * get an array of option and convert it to option of array
+ *
+ * this function have the same behavior of `A.sequence(O.option)` but it's optimized and perform better
+ *
+ * @example
+ *
+ * import * as A from 'fp-ts/Array'
+ * import { sequenceArray, some, none, fromPredicate } from 'fp-ts/Option'
+ * import { pipe } from 'fp-ts/function'
+ *
+ * const arr = A.range(0, 10)
+ * assert.deepStrictEqual(pipe(arr, A.map(some), sequenceArray), some(arr))
+ * assert.deepStrictEqual(pipe(arr, A.map(fromPredicate(x => x > 8)), sequenceArray), none)
+ *
+ * @since 2.9.0
+ */
+export const sequenceArray: <A>(arr: ReadonlyArray<Option<A>>) => Option<ReadonlyArray<A>> = traverseArray(identity)
diff --git a/src/Reader.ts b/src/Reader.ts
index 1c0fcf5b..7f4aedec 100644
--- a/src/Reader.ts
+++ b/src/Reader.ts
@@ -403,3 +403,53 @@ export const apS: <A, N extends string, R, B>(
   name: Exclude<N, keyof A>,
   fb: Reader<R, B>
 ) => (fa: Reader<R, A>) => Reader<R, { [K in keyof A | N]: K extends keyof A ? A[K] : B }> = apSW
+
+// -------------------------------------------------------------------------------------
+// array utils
+// -------------------------------------------------------------------------------------
+
+/**
+ *
+ * @since 2.9.0
+ */
+export const traverseArrayWithIndex: <R, A, B>(
+  f: (index: number, a: A) => Reader<R, B>
+) => (arr: ReadonlyArray<A>) => Reader<R, ReadonlyArray<B>> = (f) => (arr) => (r) => arr.map((x, i) => f(i, x)(r))
+
+/**
+ * this function have the same behavior of `A.traverse(R.reader)` but it's stack safe and optimized
+ *
+ * @example
+ * import * as RA from 'fp-ts/ReadonlyArray'
+ * import { traverseArray, Reader } from 'fp-ts/Reader'
+ * import { pipe } from 'fp-ts/function'
+ *
+ * const add: (x: number) => Reader<{value:number}, number> = x => config => x + config.value
+ * const arr = RA.range(0, 100)
+ *
+ * assert.deepStrictEqual(pipe(arr, traverseArray(add))({value: 3}), pipe(arr, RA.map(x => x + 3)))
+ *
+ * @since 2.9.0
+ */
+export const traverseArray: <R, A, B>(
+  f: (a: A) => Reader<R, B>
+) => (arr: ReadonlyArray<A>) => Reader<R, ReadonlyArray<B>> = (f) => traverseArrayWithIndex((_, a) => f(a))
+
+/**
+ * this function have the same behavior of `A.sequence(R.reader)` but it's stack safe and optimized
+ *
+ * @example
+ * import * as RA from 'fp-ts/ReadonlyArray'
+ * import { sequenceArray, Reader } from 'fp-ts/Reader'
+ * import { pipe } from 'fp-ts/function'
+ *
+ * const add: (x: number) => Reader<{value:number}, number> = x => config => x + config.value
+ * const arr = RA.range(0, 100)
+ *
+ * assert.deepStrictEqual(pipe(arr, RA.map(add), sequenceArray)({value: 3}), pipe(arr, RA.map(x => x + 3)))
+ *
+ * @since 2.9.0
+ */
+export const sequenceArray: <R, A>(arr: ReadonlyArray<Reader<R, A>>) => Reader<R, ReadonlyArray<A>> = traverseArray(
+  identity
+)
diff --git a/src/ReaderEither.ts b/src/ReaderEither.ts
index 02ab810c..cf3a8505 100644
--- a/src/ReaderEither.ts
+++ b/src/ReaderEither.ts
@@ -674,3 +674,29 @@ export const apS: <A, N extends string, R, E, B>(
   name: Exclude<N, keyof A>,
   fb: ReaderEither<R, E, B>
 ) => (fa: ReaderEither<R, E, A>) => ReaderEither<R, E, { [K in keyof A | N]: K extends keyof A ? A[K] : B }> = apSW
+
+// -------------------------------------------------------------------------------------
+// array utils
+// -------------------------------------------------------------------------------------
+
+/**
+ * @since 2.9.0
+ */
+export const traverseArrayWithIndex: <R, E, A, B>(
+  f: (index: number, a: A) => ReaderEither<R, E, B>
+) => (arr: ReadonlyArray<A>) => ReaderEither<R, E, ReadonlyArray<B>> = (f) =>
+  flow(R.traverseArrayWithIndex(f), R.map(E.sequenceArray))
+
+/**
+ * @since 2.9.0
+ */
+export const traverseArray: <R, E, A, B>(
+  f: (a: A) => ReaderEither<R, E, B>
+) => (arr: ReadonlyArray<A>) => ReaderEither<R, E, ReadonlyArray<B>> = (f) => traverseArrayWithIndex((_, a) => f(a))
+
+/**
+ * @since 2.9.0
+ */
+export const sequenceArray: <R, E, A>(
+  arr: ReadonlyArray<ReaderEither<R, E, A>>
+) => ReaderEither<R, E, ReadonlyArray<A>> = traverseArray(identity)
diff --git a/src/ReaderTask.ts b/src/ReaderTask.ts
index 7439b5ec..8b964001 100644
--- a/src/ReaderTask.ts
+++ b/src/ReaderTask.ts
@@ -421,3 +421,29 @@ export const apS: <A, N extends string, R, B>(
   name: Exclude<N, keyof A>,
   fb: ReaderTask<R, B>
 ) => (fa: ReaderTask<R, A>) => ReaderTask<R, { [K in keyof A | N]: K extends keyof A ? A[K] : B }> = apSW
+
+// -------------------------------------------------------------------------------------
+// array utils
+// -------------------------------------------------------------------------------------
+
+/**
+ * @since 2.9.0
+ */
+export const traverseArrayWithIndex: <R, A, B>(
+  f: (index: number, a: A) => ReaderTask<R, B>
+) => (arr: ReadonlyArray<A>) => ReaderTask<R, ReadonlyArray<B>> = (f) =>
+  flow(R.traverseArrayWithIndex(f), R.map(T.sequenceArray))
+
+/**
+ * @since 2.9.0
+ */
+export const traverseArray: <R, A, B>(
+  f: (a: A) => ReaderTask<R, B>
+) => (arr: ReadonlyArray<A>) => ReaderTask<R, ReadonlyArray<B>> = (f) => traverseArrayWithIndex((_, a) => f(a))
+
+/**
+ * @since 2.9.0
+ */
+export const sequenceArray: <R, A>(
+  arr: ReadonlyArray<ReaderTask<R, A>>
+) => ReaderTask<R, ReadonlyArray<A>> = traverseArray(identity)
diff --git a/src/ReaderTaskEither.ts b/src/ReaderTaskEither.ts
index 997d2f1b..53419e69 100644
--- a/src/ReaderTaskEither.ts
+++ b/src/ReaderTaskEither.ts
@@ -893,3 +893,64 @@ export const apS: <A, N extends string, R, E, B>(
 ) => (
   fa: ReaderTaskEither<R, E, A>
 ) => ReaderTaskEither<R, E, { [K in keyof A | N]: K extends keyof A ? A[K] : B }> = apSW
+
+// -------------------------------------------------------------------------------------
+// array utils
+// -------------------------------------------------------------------------------------
+
+/**
+ * @since 2.9.0
+ */
+export const traverseArrayWithIndex: <R, E, A, B>(
+  f: (index: number, a: A) => ReaderTaskEither<R, E, B>
+) => (arr: ReadonlyArray<A>) => ReaderTaskEither<R, E, ReadonlyArray<B>> = (f) => (arr) => (r) => () =>
+  Promise.all(arr.map((x, i) => f(i, x)(r)())).then(E.sequenceArray)
+
+/**
+ * @since 2.9.0
+ */
+export const traverseArray: <R, E, A, B>(
+  f: (a: A) => ReaderTaskEither<R, E, B>
+) => (arr: ReadonlyArray<A>) => ReaderTaskEither<R, E, ReadonlyArray<B>> = (f) => traverseArrayWithIndex((_, a) => f(a))
+
+/**
+ * @since 2.9.0
+ */
+export const sequenceArray: <R, E, A>(
+  arr: ReadonlyArray<ReaderTaskEither<R, E, A>>
+) => ReaderTaskEither<R, E, ReadonlyArray<A>> = traverseArray(identity)
+
+/**
+ * @since 2.9.0
+ */
+export const traverseSeqArrayWithIndex: <R, E, A, B>(
+  f: (index: number, a: A) => ReaderTaskEither<R, E, B>
+) => (arr: ReadonlyArray<A>) => ReaderTaskEither<R, E, ReadonlyArray<B>> = (f) => (arr) => (r) => async () => {
+  // tslint:disable-next-line: readonly-array
+  const result = []
+
+  for (let i = 0; i < arr.length; i++) {
+    const b = await f(i, arr[i])(r)()
+    if (E.isLeft(b)) {
+      return b
+    }
+    result.push(b.right)
+  }
+
+  return E.right(result)
+}
+
+/**
+ * @since 2.9.0
+ */
+export const traverseSeqArray: <R, E, A, B>(
+  f: (a: A) => ReaderTaskEither<R, E, B>
+) => (arr: ReadonlyArray<A>) => ReaderTaskEither<R, E, ReadonlyArray<B>> = (f) =>
+  traverseSeqArrayWithIndex((_, a) => f(a))
+
+/**
+ * @since 2.9.0
+ */
+export const sequenceSeqArray: <R, E, A>(
+  arr: ReadonlyArray<ReaderTaskEither<R, E, A>>
+) => ReaderTaskEither<R, E, ReadonlyArray<A>> = traverseSeqArray(identity)
diff --git a/src/ReadonlyArray.ts b/src/ReadonlyArray.ts
index a90c048d..426c83e9 100644
--- a/src/ReadonlyArray.ts
+++ b/src/ReadonlyArray.ts
@@ -1909,6 +1909,7 @@ export const reduceRightWithIndex: <A, B>(b: B, f: (i: number, a: A, b: B) => B)
 ) => (fa) => fa.reduceRight((b, a, i) => f(i, a, b), b)
 
 /**
+ * **for optimized and stack safe version check the data types `traverseArray` function**
  * @category Traversable
  * @since 2.6.3
  */
@@ -1920,6 +1921,7 @@ export const traverse: PipeableTraverse1<URI> = <F>(
 }
 
 /**
+ * **for optimized and stack safe version check the data types `sequenceArray` function**
  * @category Traversable
  * @since 2.6.3
  */
@@ -1935,6 +1937,7 @@ export const sequence: Traversable1<URI>['sequence'] = <F>(F: ApplicativeHKT<F>)
 }
 
 /**
+ * **for optimized and stack safe version check the data types `traverseArrayWithIndex` function**
  * @category TraversableWithIndex
  * @since 2.6.3
  */
diff --git a/src/State.ts b/src/State.ts
index 626fc728..706c2d7d 100644
--- a/src/State.ts
+++ b/src/State.ts
@@ -303,3 +303,64 @@ export const apS = <A, N extends string, S, B>(
     map((a) => (b: B) => bind_(a, name, b)),
     ap(fb)
   )
+
+// -------------------------------------------------------------------------------------
+// array utils
+// -------------------------------------------------------------------------------------
+
+/**
+ * @since 2.9.0
+ */
+export const traverseArrayWithIndex: <A, S, B>(
+  f: (index: number, a: A) => State<S, B>
+) => (arr: ReadonlyArray<A>) => State<S, ReadonlyArray<B>> = (f) => (arr) => (s) => {
+  let lastState = s
+  // tslint:disable-next-line: readonly-array
+  const values = []
+
+  for (let i = 0; i < arr.length; i++) {
+    const [newValue, newState] = f(i, arr[i])(lastState)
+    values.push(newValue)
+    lastState = newState
+  }
+
+  return [values, lastState]
+}
+
+/**
+ * This function has the same behavior of `A.traverse(S.State)` but it's stack safe and optimized
+ *
+ * @example
+ * import * as RA from 'fp-ts/ReadonlyArray'
+ * import { traverseArray, State } from 'fp-ts/State'
+ * import { pipe, tuple } from 'fp-ts/function'
+ *
+ * const add = (n: number): State<number, number> => (s: number) => tuple(n, n + s)
+ * const arr = RA.range(0, 100)
+ *
+ * assert.deepStrictEqual(pipe(arr, traverseArray(add))(0), [arr, arr.reduce((p, c) => p + c, 0)])
+ *
+ * @since 2.9
+ */
+export const traverseArray: <A, S, B>(
+  f: (a: A) => State<S, B>
+) => (arr: ReadonlyArray<A>) => State<S, ReadonlyArray<B>> = (f) => traverseArrayWithIndex((_, a) => f(a))
+
+/**
+ * This function has the same behavior of `A.sequence(S.State)` but it's stack safe and optimized
+ *
+ * @example
+ * import * as RA from 'fp-ts/ReadonlyArray'
+ * import { sequenceArray, State } from 'fp-ts/State'
+ * import { pipe, tuple } from 'fp-ts/function'
+ *
+ * const add = (n: number): State<number, number> => (s: number) => tuple(n, n + s)
+ * const arr = RA.range(0, 100)
+ *
+ * assert.deepStrictEqual(pipe(arr, RA.map(add), sequenceArray)(0), [arr, arr.reduce((p, c) => p + c, 0)])
+ *
+ * @since 2.9
+ */
+export const sequenceArray: <S, A>(arr: ReadonlyArray<State<S, A>>) => State<S, ReadonlyArray<A>> = traverseArray(
+  identity
+)
diff --git a/src/StateReaderTaskEither.ts b/src/StateReaderTaskEither.ts
index d8b89b63..49b06bb1 100644
--- a/src/StateReaderTaskEither.ts
+++ b/src/StateReaderTaskEither.ts
@@ -850,3 +850,47 @@ export const apS: <A, N extends string, S, R, E, B>(
 ) => (
   fa: StateReaderTaskEither<S, R, E, A>
 ) => StateReaderTaskEither<S, R, E, { [K in keyof A | N]: K extends keyof A ? A[K] : B }> = apSW
+
+// -------------------------------------------------------------------------------------
+// array utils
+// -------------------------------------------------------------------------------------
+
+/**
+ * @since 2.9.0
+ */
+export const traverseArrayWithIndex: <S, R, E, A, B>(
+  f: (index: number, a: A) => StateReaderTaskEither<S, R, E, B>
+) => (arr: ReadonlyArray<A>) => StateReaderTaskEither<S, R, E, ReadonlyArray<B>> = (f) => (arr) => (s) => (
+  r
+) => async () => {
+  let lastState = s
+  // tslint:disable-next-line: readonly-array
+  const result = []
+  for (let i = 0; i < arr.length; i++) {
+    const b = await f(i, arr[i])(lastState)(r)()
+
+    if (E.isLeft(b)) {
+      return b
+    }
+    const [newValue, newState] = b.right
+    result.push(newValue)
+    lastState = newState
+  }
+
+  return E.right([result, lastState])
+}
+
+/**
+ * @since 2.9.0
+ */
+export const traverseArray: <S, R, E, A, B>(
+  f: (a: A) => StateReaderTaskEither<S, R, E, B>
+) => (arr: ReadonlyArray<A>) => StateReaderTaskEither<S, R, E, ReadonlyArray<B>> = (f) =>
+  traverseArrayWithIndex((_, a) => f(a))
+
+/**
+ * @since 2.9.0
+ */
+export const sequenceArray: <S, R, E, A>(
+  arr: ReadonlyArray<StateReaderTaskEither<S, R, E, A>>
+) => StateReaderTaskEither<S, R, E, ReadonlyArray<A>> = traverseArray(identity)
diff --git a/src/Task.ts b/src/Task.ts
index c775beb7..5722caff 100644
--- a/src/Task.ts
+++ b/src/Task.ts
@@ -422,3 +422,101 @@ export const apS = <A, N extends string, B>(
     map((a) => (b: B) => bind_(a, name, b)),
     ap(fb)
   )
+
+// -------------------------------------------------------------------------------------
+// array utils
+// -------------------------------------------------------------------------------------
+
+/**
+ * @since 2.9.0
+ */
+export const traverseArrayWithIndex: <A, B>(
+  f: (index: number, a: A) => Task<B>
+) => (arr: ReadonlyArray<A>) => Task<ReadonlyArray<B>> = (f) => (arr) => () => Promise.all(arr.map((x, i) => f(i, x)()))
+
+/**
+ * this function map array to task using provided function and transform it to a task of array.
+ *
+ * this function have the same behavior of `A.traverse(T.task)` but it's stack safe.
+ *
+ * > **This function run all task in parallel for sequential use `traverseSeqArray` **
+ *
+ * @example
+ * import { range } from 'fp-ts/ReadonlyArray'
+ * import { pipe } from 'fp-ts/function'
+ * import { of, traverseArray } from 'fp-ts/Task'
+ * async function test() {
+ *   const arr = range(0, 10)
+ *   assert.deepStrictEqual(await pipe(arr, traverseArray(of))(), arr)
+ * }
+ *
+ * test()
+ *
+ * @since 2.9.0
+ */
+export const traverseArray: <A, B>(f: (a: A) => Task<B>) => (arr: ReadonlyArray<A>) => Task<ReadonlyArray<B>> = (f) =>
+  traverseArrayWithIndex((_, a) => f(a))
+
+/**
+ * this function works like `Promise.all` it will get an array of tasks and return a task of array.
+ *
+ * this function have the same behavior of `A.sequence(T.task)` but it's stack safe.
+ *
+ * > **This function run all task in parallel for sequential use `sequenceSeqArray` **
+ *
+ * @example
+ * import * as RA from 'fp-ts/ReadonlyArray'
+ * import { pipe } from 'fp-ts/function'
+ * import { of, sequenceArray } from 'fp-ts/Task'
+ *
+ * async function test() {
+ *   const arr = RA.range(1, 10)
+ *   assert.deepStrictEqual(await pipe(arr, RA.map(of), sequenceArray)(), arr)
+ * }
+ *
+ * test()
+ *
+ * @since 2.9.0
+ */
+export const sequenceArray: <A>(arr: ReadonlyArray<Task<A>>) => Task<ReadonlyArray<A>> = (arr) => () =>
+  Promise.all(arr.map((x) => x()))
+/**
+ * @since 2.9.0
+ */
+export const traverseSeqArrayWithIndex: <A, B>(
+  f: (index: number, a: A) => Task<B>
+) => (arr: ReadonlyArray<A>) => Task<ReadonlyArray<B>> = (f) => (arr) => async () => {
+  // tslint:disable-next-line: readonly-array
+  const result = []
+  for (let i = 0; i < arr.length; i++) {
+    const r = await f(i, arr[i])()
+    result.push(r)
+  }
+
+  return result
+}
+
+/**
+ * runs an action for every element in array then run task sequential, and accumulates the results in the array.
+ *
+ * this function have the same behavior of `A.traverse(T.taskSeq)` but it's stack safe.
+ *
+ * > **This function run all task sequentially for parallel use `traverseArray` **
+ *
+ *
+ * @since 2.9.0
+ */
+export const traverseSeqArray: <A, B>(f: (a: A) => Task<B>) => (arr: ReadonlyArray<A>) => Task<ReadonlyArray<B>> = (
+  f
+) => traverseSeqArrayWithIndex((_, a) => f(a))
+
+/**
+ * run tasks in array sequential and give a task of array
+ *
+ * this function have the same behavior of `A.sequence(T.taskSeq)` but it's stack safe.
+ *
+ * > **This function run all task sequentially for parallel use `sequenceArray` **
+ *
+ * @since 2.9.0
+ */
+export const sequenceSeqArray: <A>(arr: ReadonlyArray<Task<A>>) => Task<ReadonlyArray<A>> = traverseSeqArray(identity)
diff --git a/src/TaskEither.ts b/src/TaskEither.ts
index a4568589..54c5da1c 100644
--- a/src/TaskEither.ts
+++ b/src/TaskEither.ts
@@ -919,3 +919,136 @@ export const apS: <A, N extends string, E, B>(
   name: Exclude<N, keyof A>,
   fb: TaskEither<E, B>
 ) => (fa: TaskEither<E, A>) => TaskEither<E, { [K in keyof A | N]: K extends keyof A ? A[K] : B }> = apSW
+
+// -------------------------------------------------------------------------------------
+// array utils
+// -------------------------------------------------------------------------------------
+
+/**
+ * @since 2.9.0
+ */
+export const traverseArrayWithIndex: <A, B, E>(
+  f: (index: number, a: A) => TaskEither<E, B>
+) => (arr: ReadonlyArray<A>) => TaskEither<E, ReadonlyArray<B>> = (f) => (arr) =>
+  pipe(arr, T.traverseArrayWithIndex(f), T.map(E.sequenceArray))
+
+/**
+ * this function have the same behavior of `A.traverse(TE.taskEither)` but it's stack safe and perform better
+ *
+ * *this function run all tasks in parallel and does not bail out, for sequential version use `traverseSeqArray`*
+ *
+ * @example
+ *
+ * import * as TE from 'fp-ts/TaskEither'
+ * import * as A from 'fp-ts/Array'
+ * import { right } from 'fp-ts/Either'
+ * import { pipe } from 'fp-ts/function'
+ *
+ * const PostRepo = {
+ *  findById : (id: number) => TE.of({id, title: ''})
+ * }
+ *
+ * const findAllPosts = (ids:number[]) => pipe(ids, TE.traverseArray(PostRepo.findById))
+ *
+ * async function test() {
+ *   const ids = A.range(0, 10)
+ *
+ *   assert.deepStrictEqual(
+ *     await findAllPosts(ids)(),
+ *     right(
+ *       pipe(
+ *         ids,
+ *         A.map((id) => ({ id, title: ''}))
+ *       )
+ *     )
+ *   )
+ * }
+ *
+ * test()
+ *
+ * @since 2.9.0
+ */
+export const traverseArray: <A, B, E>(
+  f: (a: A) => TaskEither<E, B>
+) => (arr: ReadonlyArray<A>) => TaskEither<E, ReadonlyArray<B>> = (f) => traverseArrayWithIndex((_, a) => f(a))
+
+/**
+ * this function have the same behavior of `A.sequence(TE.taskEither)` but it's stack safe and perform better
+ *
+ * *this function run all tasks in parallel and does not bail out, for sequential version use `sequenceSeqArray`*
+ *
+ * @example
+ *
+ * import * as TE from 'fp-ts/TaskEither'
+ * import * as A from 'fp-ts/Array'
+ * import { right } from 'fp-ts/Either'
+ * import { pipe } from 'fp-ts/function'
+ *
+ * const PostRepo = {
+ *  findById : (id: number) => TE.of({id, title: ''})
+ * }
+ *
+ * const findAllPosts = (ids:number[]) => pipe(ids, A.map(PostRepo.findById), TE.sequenceArray)
+ *
+ * async function test() {
+ *   const ids = A.range(0, 10)
+ *
+ *   assert.deepStrictEqual(
+ *     await findAllPosts(ids)(),
+ *     right(
+ *       pipe(
+ *         ids,
+ *         A.map((id) => ({ id, title: ''}))
+ *       )
+ *     )
+ *   )
+ * }
+ *
+ * test()
+ *
+ * @since 2.9.0
+ */
+export const sequenceArray: <A, E>(
+  arr: ReadonlyArray<TaskEither<E, A>>
+) => TaskEither<E, ReadonlyArray<A>> = traverseArray(identity)
+
+/**
+ * @since 2.9.0
+ */
+export const traverseSeqArrayWithIndex: <A, B, E>(
+  f: (index: number, a: A) => TaskEither<E, B>
+) => (arr: ReadonlyArray<A>) => TaskEither<E, ReadonlyArray<B>> = (f) => (arr) => async () => {
+  // tslint:disable-next-line: readonly-array
+  const result = []
+  for (let i = 0; i < arr.length; i++) {
+    const e = await f(i, arr[i])()
+    if (E.isLeft(e)) {
+      return e
+    }
+    result.push(e.right)
+  }
+
+  return E.right(result)
+}
+
+/**
+ * this function have the same behavior of `A.traverse(TE.taskEitherSeq)` but it's stack safe and perform better
+ *
+ * *this function run all tasks in sequential order and bails out on left side of either, for parallel version use `traverseArray`*
+ *
+ * @since 2.9.0
+ */
+export const traverseSeqArray: <A, B, E>(
+  f: (a: A) => TaskEither<E, B>
+) => (arr: ReadonlyArray<A>) => TaskEither<E, ReadonlyArray<B>> = (f) => traverseSeqArrayWithIndex((_, a) => f(a))
+
+/**
+ * this function have the same behavior of `A.sequence(TE.taskEitherSeq)` but it's stack safe and perform better
+ *
+ * *this function run all tasks in sequential order and bails out on left side of either, for parallel version use `sequenceArray`*
+ *
+ * @since 2.9.0
+ */
+export const sequenceSeqArray: <A, E>(
+  arr: ReadonlyArray<TaskEither<E, A>>
+) => TaskEither<E, ReadonlyArray<A>> = traverseSeqArray(identity)


Test patch:
diff --git a/test/Either.ts b/test/Either.ts
index a56bfc6e..89df70ca 100644
--- a/test/Either.ts
+++ b/test/Either.ts
@@ -8,6 +8,7 @@ import { semigroupSum } from '../src/Semigroup'
 import { showString } from '../src/Show'
 import * as T from '../src/Task'
 import { sequenceT } from '../src/Apply'
+import * as A from '../src/Array'
 
 describe('Either', () => {
   describe('pipeables', () => {
@@ -603,4 +604,124 @@ describe('Either', () => {
     assert.deepStrictEqual(f(_.right(-1)), _.left('error'))
     assert.deepStrictEqual(f(_.left('a')), _.left('a'))
   })
+
+  describe('array utils', () => {
+    it('sequenceArray', () => {
+      const arr = A.range(0, 10)
+      assert.deepStrictEqual(pipe(arr, A.map(_.right), _.sequenceArray), _.right(arr))
+      assert.deepStrictEqual(pipe(arr, A.map(_.right), A.cons(_.left('a')), _.sequenceArray), _.left('a'))
+    })
+
+    it('traverseArrayWithIndex', () => {
+      const arr = A.range(0, 10)
+      assert.deepStrictEqual(
+        pipe(
+          arr,
+          _.traverseArrayWithIndex((index, _data) => _.right(index))
+        ),
+        _.right(arr)
+      )
+      assert.deepStrictEqual(
+        pipe(
+          arr,
+          _.traverseArray(
+            _.fromPredicate(
+              (x) => x > 5,
+              () => 'a'
+            )
+          )
+        ),
+        _.left('a')
+      )
+    })
+
+    it('traverseArray', () => {
+      const arr = A.range(0, 10)
+      assert.deepStrictEqual(
+        pipe(
+          arr,
+          _.traverseArray((x) => _.right(x))
+        ),
+        _.right(arr)
+      )
+      assert.deepStrictEqual(
+        pipe(
+          arr,
+          _.traverseArray(
+            _.fromPredicate(
+              (x) => x > 5,
+              () => 'a'
+            )
+          )
+        ),
+        _.left('a')
+      )
+    })
+  })
+  it('fromNullableK', () => {
+    const f = _.fromNullableK('error')((n: number) => (n > 0 ? n : null))
+    assert.deepStrictEqual(f(1), _.right(1))
+    assert.deepStrictEqual(f(-1), _.left('error'))
+  })
+
+  it('chainNullableK', () => {
+    const f = _.chainNullableK('error')((n: number) => (n > 0 ? n : null))
+    assert.deepStrictEqual(f(_.right(1)), _.right(1))
+    assert.deepStrictEqual(f(_.right(-1)), _.left('error'))
+    assert.deepStrictEqual(f(_.left('a')), _.left('a'))
+  })
+
+  describe('array utils', () => {
+    it('sequenceArray', () => {
+      const arr = A.range(0, 10)
+      assert.deepStrictEqual(pipe(arr, A.map(_.right), _.sequenceArray), _.right(arr))
+      assert.deepStrictEqual(pipe(arr, A.map(_.right), A.cons(_.left('a')), _.sequenceArray), _.left('a'))
+    })
+
+    it('traverseArrayWithIndex', () => {
+      const arr = A.range(0, 10)
+      assert.deepStrictEqual(
+        pipe(
+          arr,
+          _.traverseArrayWithIndex((index, _data) => _.right(index))
+        ),
+        _.right(arr)
+      )
+      assert.deepStrictEqual(
+        pipe(
+          arr,
+          _.traverseArray(
+            _.fromPredicate(
+              (x) => x > 5,
+              () => 'a'
+            )
+          )
+        ),
+        _.left('a')
+      )
+    })
+
+    it('traverseArray', () => {
+      const arr = A.range(0, 10)
+      assert.deepStrictEqual(
+        pipe(
+          arr,
+          _.traverseArray((x) => _.right(x))
+        ),
+        _.right(arr)
+      )
+      assert.deepStrictEqual(
+        pipe(
+          arr,
+          _.traverseArray(
+            _.fromPredicate(
+              (x) => x > 5,
+              () => 'a'
+            )
+          )
+        ),
+        _.left('a')
+      )
+    })
+  })
 })
diff --git a/test/IO.ts b/test/IO.ts
index c9c33d59..fc078413 100644
--- a/test/IO.ts
+++ b/test/IO.ts
@@ -2,6 +2,7 @@ import * as assert from 'assert'
 import * as _ from '../src/IO'
 import { semigroupSum } from '../src/Semigroup'
 import { monoidSum } from '../src/Monoid'
+import * as RA from '../src/ReadonlyArray'
 import * as E from '../src/Either'
 import { pipe } from '../src/function'
 
@@ -78,4 +79,27 @@ describe('IO', () => {
   it('apS', () => {
     assert.deepStrictEqual(pipe(_.of(1), _.bindTo('a'), _.apS('b', _.of('b')))(), { a: 1, b: 'b' })
   })
+
+  describe('array utils', () => {
+    it('sequenceArray', () => {
+      const arr = RA.range(0, 100)
+      assert.deepStrictEqual(pipe(arr, RA.map(_.of), _.sequenceArray)(), arr)
+    })
+
+    it('traverseArray', () => {
+      const arr = RA.range(0, 100)
+      assert.deepStrictEqual(pipe(arr, _.traverseArray(_.of))(), arr)
+    })
+
+    it('traverseArrayWithIndex', () => {
+      const arr = RA.range(0, 100)
+      assert.deepStrictEqual(
+        pipe(
+          arr,
+          _.traverseArrayWithIndex((index, _data) => _.of(index))
+        )(),
+        arr
+      )
+    })
+  })
 })
diff --git a/test/IOEither.ts b/test/IOEither.ts
index 2aa304aa..24c0c6e4 100644
--- a/test/IOEither.ts
+++ b/test/IOEither.ts
@@ -1,10 +1,10 @@
 import * as assert from 'assert'
 import { sequenceT } from '../src/Apply'
-import { getMonoid } from '../src/Array'
 import * as E from '../src/Either'
 import { pipe } from '../src/function'
 import * as I from '../src/IO'
 import * as _ from '../src/IOEither'
+import * as A from '../src/Array'
 import { monoidString } from '../src/Monoid'
 import { none, some } from '../src/Option'
 import { pipeable } from '../src/pipeable'
@@ -333,7 +333,7 @@ describe('IOEither', () => {
   })
 
   describe('getFilterable', () => {
-    const F_ = _.getFilterable(getMonoid<string>())
+    const F_ = _.getFilterable(A.getMonoid<string>())
     const { filter } = pipeable(F_)
 
     it('filter', async () => {
@@ -378,4 +378,63 @@ describe('IOEither', () => {
       E.right({ a: 1, b: 'b' })
     )
   })
+
+  describe('array utils', () => {
+    it('sequenceArray', () => {
+      const arr = A.range(0, 10)
+      assert.deepStrictEqual(pipe(arr, A.map(_.of), _.sequenceArray)(), E.right(arr))
+    })
+
+    it('traverseArray', () => {
+      const arr = A.range(0, 10)
+      assert.deepStrictEqual(pipe(arr, _.traverseArray(_.of))(), E.right(arr))
+    })
+
+    it('traverseArrayWithIndex', () => {
+      const arr = A.replicate(3, 1)
+      assert.deepStrictEqual(
+        pipe(
+          arr,
+          _.traverseArrayWithIndex((index, _data) => _.of(index))
+        )(),
+        E.right([0, 1, 2])
+      )
+    })
+
+    it('sequenceSeqArray', () => {
+      const arr = A.range(0, 10)
+      assert.deepStrictEqual(pipe(arr, A.map(_.of), _.sequenceSeqArray)(), E.right(arr))
+    })
+
+    it('traverseSeqArray', () => {
+      const arr = A.range(0, 10)
+      assert.deepStrictEqual(pipe(arr, _.traverseSeqArray(_.of))(), E.right(arr))
+    })
+
+    it('traverseSeqArrayWithIndex', () => {
+      const arr = A.replicate(3, 1)
+      assert.deepStrictEqual(
+        pipe(
+          arr,
+          _.traverseSeqArrayWithIndex((index, _data) =>
+            pipe(
+              index,
+              _.fromPredicate(
+                (index) => index < 1,
+                () => 'ERROR'
+              )
+            )
+          )
+        )(),
+        E.left('ERROR')
+      )
+      assert.deepStrictEqual(
+        pipe(
+          arr,
+          _.traverseSeqArrayWithIndex((index, _data) => _.of(index))
+        )(),
+        E.right([0, 1, 2])
+      )
+    })
+  })
 })
diff --git a/test/Option.ts b/test/Option.ts
index 3f98509c..4514c35e 100644
--- a/test/Option.ts
+++ b/test/Option.ts
@@ -469,4 +469,66 @@ describe('Option', () => {
     assert.deepStrictEqual(f(1), _.some(1))
     assert.deepStrictEqual(f(-1), _.none)
   })
+  // -------------------------------------------------------------------------------------
+  // array utils
+  // -------------------------------------------------------------------------------------
+
+  it('sequenceArray', () => {
+    const arr = A.range(0, 10)
+    assert.deepStrictEqual(pipe(arr, A.map(_.some), _.sequenceArray), _.some(arr))
+
+    assert.deepStrictEqual(pipe(arr, A.map(_.fromPredicate((x) => x > 5)), _.sequenceArray), _.none)
+  })
+
+  it('traverseArray', () => {
+    const arr = A.range(0, 10)
+    assert.deepStrictEqual(pipe(arr, _.traverseArray(_.some)), _.some(arr))
+    assert.deepStrictEqual(pipe(arr, _.traverseArray(_.fromPredicate((x) => x > 5))), _.none)
+  })
+
+  it('traverseArrayWithIndex', () => {
+    const arr = A.range(0, 10)
+    assert.deepStrictEqual(
+      pipe(
+        arr,
+        _.traverseArrayWithIndex((index, _data) => _.some(index))
+      ),
+      _.some(arr)
+    )
+    assert.deepStrictEqual(pipe(arr, _.traverseArrayWithIndex(_.fromPredicate((x) => x > 5))), _.none)
+  })
+
+  it('fromNullableK', () => {
+    const f = _.fromNullableK((n: number) => (n > 0 ? n : null))
+    assert.deepStrictEqual(f(1), _.some(1))
+    assert.deepStrictEqual(f(-1), _.none)
+  })
+  // -------------------------------------------------------------------------------------
+  // array utils
+  // -------------------------------------------------------------------------------------
+
+  it('sequenceArray', () => {
+    const arr = A.range(0, 10)
+    assert.deepStrictEqual(pipe(arr, A.map(_.some), _.sequenceArray), _.some(arr))
+
+    assert.deepStrictEqual(pipe(arr, A.map(_.fromPredicate((x) => x > 5)), _.sequenceArray), _.none)
+  })
+
+  it('traverseArray', () => {
+    const arr = A.range(0, 10)
+    assert.deepStrictEqual(pipe(arr, _.traverseArray(_.some)), _.some(arr))
+    assert.deepStrictEqual(pipe(arr, _.traverseArray(_.fromPredicate((x) => x > 5))), _.none)
+  })
+
+  it('traverseArrayWithIndex', () => {
+    const arr = A.range(0, 10)
+    assert.deepStrictEqual(
+      pipe(
+        arr,
+        _.traverseArrayWithIndex((index, _data) => _.some(index))
+      ),
+      _.some(arr)
+    )
+    assert.deepStrictEqual(pipe(arr, _.traverseArrayWithIndex(_.fromPredicate((x) => x > 5))), _.none)
+  })
 })
diff --git a/test/Reader.ts b/test/Reader.ts
index ba595fe7..b7e28512 100644
--- a/test/Reader.ts
+++ b/test/Reader.ts
@@ -3,6 +3,7 @@ import * as _ from '../src/Reader'
 import { semigroupSum } from '../src/Semigroup'
 import { monoidSum } from '../src/Monoid'
 import { pipe } from '../src/function'
+import * as RA from '../src/ReadonlyArray'
 
 interface Env {
   readonly count: number
@@ -126,4 +127,27 @@ describe('Reader', () => {
   it('apS', () => {
     assert.deepStrictEqual(pipe(_.of(1), _.bindTo('a'), _.apS('b', _.of('b')))(undefined), { a: 1, b: 'b' })
   })
+
+  describe('array utils', () => {
+    it('sequenceArray', () => {
+      const arr = RA.range(0, 10)
+      assert.deepStrictEqual(pipe(arr, RA.map(_.of), _.sequenceArray)(undefined), arr)
+    })
+
+    it('traverseArray', () => {
+      const arr = RA.range(0, 10)
+      assert.deepStrictEqual(pipe(arr, _.traverseArray(_.of))(undefined), arr)
+    })
+
+    it('traverseArrayWithIndex', () => {
+      const arr = RA.range(0, 10)
+      assert.deepStrictEqual(
+        pipe(
+          arr,
+          _.traverseArrayWithIndex((index, _data) => _.of(index))
+        )(undefined),
+        arr
+      )
+    })
+  })
 })
diff --git a/test/ReaderEither.ts b/test/ReaderEither.ts
index 357dce99..bdfa1d8b 100644
--- a/test/ReaderEither.ts
+++ b/test/ReaderEither.ts
@@ -4,6 +4,7 @@ import * as E from '../src/Either'
 import { pipe } from '../src/function'
 import { monoidString } from '../src/Monoid'
 import { none, some } from '../src/Option'
+import * as A from '../src/Array'
 import * as R from '../src/Reader'
 import * as _ from '../src/ReaderEither'
 import { semigroupSum } from '../src/Semigroup'
@@ -231,4 +232,27 @@ describe('ReaderEither', () => {
       E.right({ a: 1, b: 'b' })
     )
   })
+
+  describe('array utils', () => {
+    it('sequenceArray', () => {
+      const arr = A.range(1, 10)
+      assert.deepStrictEqual(pipe(arr, A.map(_.of), _.sequenceArray)({}), E.right(arr))
+    })
+
+    it('traverseArray', () => {
+      const arr = A.range(1, 10)
+      assert.deepStrictEqual(pipe(arr, _.traverseArray(_.of))({}), E.right(arr))
+    })
+
+    it('traverseArrayWithIndex', () => {
+      const arr = A.replicate(3, 1)
+      assert.deepStrictEqual(
+        pipe(
+          arr,
+          _.traverseArrayWithIndex((index, _data) => _.of(index))
+        )({}),
+        E.right([0, 1, 2])
+      )
+    })
+  })
 })
diff --git a/test/ReaderTask.ts b/test/ReaderTask.ts
index ccfec941..baf90e81 100644
--- a/test/ReaderTask.ts
+++ b/test/ReaderTask.ts
@@ -3,6 +3,7 @@ import { pipe } from '../src/function'
 import * as I from '../src/IO'
 import { monoidString } from '../src/Monoid'
 import * as R from '../src/Reader'
+import * as A from '../src/Array'
 import * as _ from '../src/ReaderTask'
 import { semigroupString } from '../src/Semigroup'
 import * as T from '../src/Task'
@@ -151,4 +152,26 @@ describe('ReaderTask', () => {
   it('apS', async () => {
     assert.deepStrictEqual(await pipe(_.of(1), _.bindTo('a'), _.apS('b', _.of('b')))(undefined)(), { a: 1, b: 'b' })
   })
+
+  describe('array utils', () => {
+    it('sequenceArray', async () => {
+      const arr = A.range(0, 10)
+      assert.deepStrictEqual(await pipe(arr, A.map(_.of), _.sequenceArray)(undefined)(), arr)
+    })
+    it('traverseArray', async () => {
+      const arr = A.range(0, 10)
+      assert.deepStrictEqual(await pipe(arr, _.traverseArray(_.of))(undefined)(), arr)
+    })
+
+    it('traverseArrayWithIndex', async () => {
+      const arr = A.replicate(3, 1)
+      assert.deepStrictEqual(
+        await pipe(
+          arr,
+          _.traverseArrayWithIndex((index, _data) => _.of(index))
+        )(undefined)(),
+        [0, 1, 2]
+      )
+    })
+  })
 })
diff --git a/test/ReaderTaskEither.ts b/test/ReaderTaskEither.ts
index 4246541d..a8b27fae 100644
--- a/test/ReaderTaskEither.ts
+++ b/test/ReaderTaskEither.ts
@@ -1,5 +1,6 @@
 import * as assert from 'assert'
 import { sequenceT } from '../src/Apply'
+import * as A from '../src/Array'
 import * as E from '../src/Either'
 import { pipe } from '../src/function'
 import * as I from '../src/IO'
@@ -400,4 +401,128 @@ describe('ReaderTaskEither', () => {
       E.right({ a: 1, b: 'b' })
     )
   })
+
+  describe('array utils', () => {
+    it('sequenceArray', async () => {
+      const arr = A.range(0, 10)
+      assert.deepStrictEqual(await pipe(arr, A.map(_.of), _.sequenceArray)(undefined)(), E.right(arr))
+      assert.deepStrictEqual(
+        await pipe(
+          arr,
+          A.map(
+            _.fromPredicate(
+              (x) => x < 5,
+              () => 'Error'
+            )
+          ),
+          _.sequenceArray
+        )(undefined)(),
+        E.left('Error')
+      )
+    })
+
+    it('traverseArray', async () => {
+      const arr = A.range(0, 10)
+      assert.deepStrictEqual(await pipe(arr, _.traverseArray(_.of))(undefined)(), E.right(arr))
+      assert.deepStrictEqual(
+        await pipe(
+          arr,
+          _.traverseArray(
+            _.fromPredicate(
+              (x) => x < 5,
+              () => 'Error'
+            )
+          )
+        )(undefined)(),
+        E.left('Error')
+      )
+    })
+
+    it('traverseArrayWithIndex', async () => {
+      const arr = A.replicate(3, 1)
+      assert.deepStrictEqual(
+        await pipe(
+          arr,
+          _.traverseArrayWithIndex((index, _data) => _.of(index))
+        )(undefined)(),
+        E.right([0, 1, 2])
+      )
+      assert.deepStrictEqual(
+        await pipe(
+          arr,
+          _.traverseArrayWithIndex((index, _data) =>
+            pipe(
+              index,
+              _.fromPredicate(
+                (x) => x < 1,
+                () => 'Error'
+              )
+            )
+          )
+        )(undefined)(),
+        E.left('Error')
+      )
+    })
+
+    it('sequenceSeqArray', async () => {
+      const arr = A.range(0, 10)
+      assert.deepStrictEqual(await pipe(arr, A.map(_.of), _.sequenceSeqArray)(undefined)(), E.right(arr))
+      assert.deepStrictEqual(
+        await pipe(
+          arr,
+          A.map(
+            _.fromPredicate(
+              (x) => x < 5,
+              () => 'Error'
+            )
+          ),
+          _.sequenceArray
+        )(undefined)(),
+        E.left('Error')
+      )
+    })
+
+    it('traverseArray', async () => {
+      const arr = A.range(0, 10)
+      assert.deepStrictEqual(await pipe(arr, _.traverseSeqArray(_.of))(undefined)(), E.right(arr))
+      assert.deepStrictEqual(
+        await pipe(
+          arr,
+          _.traverseSeqArray(
+            _.fromPredicate(
+              (x) => x < 5,
+              () => 'Error'
+            )
+          )
+        )(undefined)(),
+        E.left('Error')
+      )
+    })
+
+    it('traverseSeqArrayWithIndex', async () => {
+      const arr = A.replicate(3, 1)
+      assert.deepStrictEqual(
+        await pipe(
+          arr,
+          _.traverseSeqArrayWithIndex((index, _data) => _.of(index))
+        )(undefined)(),
+        E.right([0, 1, 2])
+      )
+      assert.deepStrictEqual(
+        await pipe(
+          arr,
+          _.traverseSeqArrayWithIndex((index, _data) =>
+            pipe(
+              index,
+              _.fromPredicate(
+                (x) => x < 1,
+                () => 'Error'
+              )
+            )
+          )
+        )(undefined)(),
+        E.left('Error')
+      )
+    })
+  })
 })
diff --git a/test/State.ts b/test/State.ts
index fbfcc732..09ebe2f0 100644
--- a/test/State.ts
+++ b/test/State.ts
@@ -1,4 +1,5 @@
 import * as assert from 'assert'
+import * as RA from '../src/ReadonlyArray'
 import { pipe, tuple } from '../src/function'
 import * as _ from '../src/State'
 
@@ -93,4 +94,29 @@ describe('State', () => {
       undefined
     ])
   })
+
+  describe('array utils', () => {
+    it('sequenceArray', () => {
+      const add = (n: number) => (s: number) => tuple(n, n + s)
+      const arr = RA.range(0, 10)
+      assert.deepStrictEqual(pipe(arr, RA.map(add), _.sequenceArray)(0), [arr, arr.reduce((p, c) => p + c, 0)])
+    })
+
+    it('traverseArray', () => {
+      const add = (n: number) => (s: number) => tuple(n, n + s)
+      const arr = RA.range(0, 10)
+      assert.deepStrictEqual(pipe(arr, _.traverseArray(add))(0), [arr, arr.reduce((p, c) => p + c, 0)])
+    })
+    it('traverseArrayWithIndex', () => {
+      const add = (n: number) => (s: number) => tuple(n, n + s)
+      const arr = RA.range(0, 10)
+      assert.deepStrictEqual(
+        pipe(
+          arr,
+          _.traverseArrayWithIndex((_i, data) => add(data))
+        )(0),
+        [arr, arr.reduce((p, c) => p + c, 0)]
+      )
+    })
+  })
 })
diff --git a/test/StateReaderTaskEither.ts b/test/StateReaderTaskEither.ts
index a016636a..751c1373 100644
--- a/test/StateReaderTaskEither.ts
+++ b/test/StateReaderTaskEither.ts
@@ -3,7 +3,7 @@ import * as E from '../src/Either'
 import * as I from '../src/IO'
 import * as IE from '../src/IOEither'
 import * as O from '../src/Option'
-import { pipe } from '../src/function'
+import { pipe, tuple } from '../src/function'
 import * as R from '../src/Reader'
 import * as RE from '../src/ReaderEither'
 import * as RTE from '../src/ReaderTaskEither'
@@ -331,4 +331,55 @@ describe('StateReaderTaskEither', () => {
       E.right([{ a: 1, b: 'b' }, undefined])
     )
   })
+
+  describe('array utils', () => {
+    it('sequenceArray', async () => {
+      const add = (n: number) => (s: number) => (_r: {}) => () => Promise.resolve(E.right(tuple(n, n + s)))
+      const arr = A.range(0, 10)
+
+      assert.deepStrictEqual(
+        await pipe(arr, A.map(add), _.sequenceArray)(0)({})(),
+        E.right([arr, arr.reduce((p, c) => p + c, 0)])
+      )
+    })
+
+    it('traverseArray', async () => {
+      const add = (n: number) => (s: number) => (_r: {}) => () => Promise.resolve(E.right(tuple(n, n + s)))
+      const arr = A.range(0, 10)
+
+      assert.deepStrictEqual(
+        await pipe(arr, _.traverseArray(add))(0)({})(),
+        E.right([arr, arr.reduce((p, c) => p + c, 0)])
+      )
+    })
+
+    it('traverseArrayWithIndex', async () => {
+      const add = (n: number) => _.rightState((s: number) => tuple(n, n + s))
+      const arr = A.range(0, 10)
+
+      assert.deepStrictEqual(
+        await pipe(
+          arr,
+          _.traverseArrayWithIndex((_index, a) =>
+            pipe(
+              a,
+              _.fromPredicate(
+                (a) => a > 5,
+                () => 'ERROR'
+              )
+            )
+          )
+        )(0)({})(),
+        E.left('ERROR')
+      )
+
+      assert.deepStrictEqual(
+        await pipe(
+          arr,
+          _.traverseArrayWithIndex((_, a) => add(a))
+        )(0)({})(),
+        E.right([arr, arr.reduce((p, c) => p + c, 0)])
+      )
+    })
+  })
 })
diff --git a/test/Task.ts b/test/Task.ts
index 100fa83b..4eba253c 100644
--- a/test/Task.ts
+++ b/test/Task.ts
@@ -3,6 +3,7 @@ import * as I from '../src/IO'
 import { monoidString } from '../src/Monoid'
 import { pipe } from '../src/function'
 import * as _ from '../src/Task'
+import * as RA from '../src/ReadonlyArray'
 import { assertSeq, assertPar } from './util'
 
 const delayReject = <A>(n: number, a: A): _.Task<A> => () =>
@@ -136,4 +137,48 @@ describe('Task', () => {
   it('apS', async () => {
     assert.deepStrictEqual(await pipe(_.of(1), _.bindTo('a'), _.apS('b', _.of('b')))(), { a: 1, b: 'b' })
   })
+
+  describe('array utils', () => {
+    it('sequenceArray', async () => {
+      const arr = RA.range(0, 10)
+      assert.deepStrictEqual(await pipe(arr, RA.map(_.of), _.sequenceArray)(), arr)
+    })
+
+    it('traverseArray', async () => {
+      const arr = RA.range(0, 10)
+      assert.deepStrictEqual(await pipe(arr, _.traverseArray(_.of))(), arr)
+    })
+
+    it('traverseArrayWithIndex', async () => {
+      const arr = RA.range(0, 10)
+      assert.deepStrictEqual(
+        await pipe(
+          arr,
+          _.traverseArrayWithIndex((index, _data) => _.of(index))
+        )(),
+        arr
+      )
+    })
+
+    it('sequenceSeqArray', async () => {
+      const arr = RA.range(0, 10)
+      assert.deepStrictEqual(await pipe(arr, RA.map(_.of), _.sequenceSeqArray)(), arr)
+    })
+
+    it('traverseSeqArray', async () => {
+      const arr = RA.range(0, 10)
+      assert.deepStrictEqual(await pipe(arr, _.traverseSeqArray(_.of))(), arr)
+    })
+
+    it('traverseSeqArrayWithIndex', async () => {
+      const arr = RA.range(0, 10)
+      assert.deepStrictEqual(
+        await pipe(
+          arr,
+          _.traverseSeqArrayWithIndex((index, _data) => _.of(index))
+        )(),
+        arr
+      )
+    })
+  })
 })
diff --git a/test/TaskEither.ts b/test/TaskEither.ts
index 65d03744..ec1df062 100644
--- a/test/TaskEither.ts
+++ b/test/TaskEither.ts
@@ -436,4 +436,75 @@ describe('TaskEither', () => {
       E.right({ a: 1, b: 'b' })
     )
   })
+
+  describe('array utils', () => {
+    it('sequenceA', async () => {
+      const arr = A.range(0, 10)
+      assert.deepStrictEqual(await pipe(arr, A.map(_.of), _.sequenceArray)(), E.right(arr))
+      assert.deepStrictEqual(
+        await pipe(
+          arr,
+          A.map(
+            _.fromPredicate(
+              (x) => x > 5,
+              () => 'a'
+            )
+          ),
+          _.sequenceArray
+        )(),
+        E.left('a')
+      )
+    })
+
+    it('traverseA', async () => {
+      const arr = A.range(0, 10)
+      assert.deepStrictEqual(await pipe(arr, _.traverseArray(_.of))(), E.right(arr))
+      assert.deepStrictEqual(
+        await pipe(
+          arr,
+          _.traverseArray(
+            _.fromPredicate(
+              (x) => x > 5,
+              () => 'a'
+            )
+          )
+        )(),
+        E.left('a')
+      )
+    })
+    it('sequenceSeqA', async () => {
+      const arr = A.range(0, 10)
+      assert.deepStrictEqual(await pipe(arr, A.map(_.of), _.sequenceSeqArray)(), E.right(arr))
+      assert.deepStrictEqual(
+        await pipe(
+          arr,
+          A.map(
+            _.fromPredicate(
+              (x) => x > 5,
+              () => 'a'
+            )
+          ),
+          _.sequenceSeqArray
+        )(),
+        E.left('a')
+      )
+    })
+
+    it('traverseSeqA', async () => {
+      const arr = A.range(0, 10)
+      assert.deepStrictEqual(await pipe(arr, _.traverseSeqArray(_.of))(), E.right(arr))
+      assert.deepStrictEqual(
+        await pipe(
+          arr,
+          _.traverseSeqArray(
+            _.fromPredicate(
+              (x) => x > 5,
+              () => 'a'
+            )
+          )
+        )(),
+        E.left('a')
+      )
+    })
+  })
 })