Repository: gcanti/fp-ts
Pull request #1025 (2019-11-23 14:15:11)

first stab at 'getReaderTaskValidation'
**Before submitting a pull request,** please make sure the following is done:

- Fork [the repository](https://github.com/gcanti/fp-ts) and create your branch from `master`.
- Run `npm install` in the repository root.
- If you've fixed a bug or added code that should be tested, add tests!
- Ensure the test suite passes (`npm test`).

**Note**. If you've fixed a bug please link the related issue or, if missing, open an issue before sending a PR.

**Note**. If you find a typo in the **documentation**, make sure to modify the corresponding source (docs are generated).

**Note**. If you want to send a PR related to `fp-ts@1.x` please create your branch from `1.x`


sledorze: @gcanti before involving more time in it, I wanted to have your feedback on it.
This would also adds `ReadTask`.
sledorze: @gcanti I get your thinking.
Last input from me before we drop; regardless of failure handling, I think it may have some value even without possible failure.
We may keep it for DX or drop it as it may be considered trivial to achieve; let me know.

Other than that, I may propose to add all the overload of the new 'xxx3C' introduced in this PR; ok to have it inside this PR (or another one?)

I've done it in the previous commit for Applicative3C (necessary for traverse test)

Remaining:
Alt3C
Apply3C
Chain3C
Functor3C
Monad3C

May I add those in this PR?
gcanti: > We may keep it for DX or drop it as it may be considered trivial to achieve; let me know

I think they are confusing, let's drop them

> May I add those in this PR?

ok
sledorze: I can't find why the coverage is not 100% on ReaderTaskEither (242) everything is covered to me
sledorze: @gcanti 
I would eat a raw habanero to have 2.2.0 released by today (and may help) :)
mikearnaldi: @sledorze @gcanti I'll gladly share the habanero with stephan trasversable on matechs-effect depends on this :)
sledorze: @gcanti I know it's a big one, if that's an issue maybe a 'next' pre-release?

sledorze: @gcanti updated for 2.3

Patch:
diff --git a/README.md b/README.md
index a22c0e42..07926634 100644
--- a/README.md
+++ b/README.md
@@ -36,10 +36,10 @@ A distinctive feature of `fp-ts` with respect to other functional libraries is i
 
 <!-- START doctoc generated TOC please keep comment here to allow auto update -->
 <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
-
 **Table of contents**
 
 - [Installation](#installation)
+  - [Consuming fp-ts](#consuming-fp-ts)
   - [TypeScript compatibility](#typescript-compatibility)
 - [Documentation](#documentation)
 - [Development](#development)
diff --git a/package-lock.json b/package-lock.json
index df415fcb..b0ce921c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "fp-ts",
-  "version": "2.1.2",
+  "version": "2.2.0",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
@@ -474,16 +474,6 @@
         "@types/yargs": "^12.0.9"
       }
     },
-    "@mrmlnc/readdir-enhanced": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
-      "integrity": "sha1-UkryQNGjYFJ7cwR17PoTRKpUDd4=",
-      "dev": true,
-      "requires": {
-        "call-me-maybe": "^1.0.1",
-        "glob-to-regexp": "^0.3.0"
-      }
-    },
     "@nodelib/fs.scandir": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.1.tgz",
@@ -502,12 +492,6 @@
         }
       }
     },
-    "@nodelib/fs.stat": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.2.tgz",
-      "integrity": "sha512-yprFYuno9FtNsSHVlSWd+nRlmGoAbqbeCwOryP6sC/zoCjhpArcRMYp19EvpSUSizJAlsXEwJv+wcWS9XaXdMw==",
-      "dev": true
-    },
     "@nodelib/fs.walk": {
       "version": "1.2.2",
       "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.2.tgz",
@@ -586,12 +570,6 @@
       "integrity": "sha1-LdNRTpM5bzYrpVUafJ/w2kBcHTg=",
       "dev": true
     },
-    "@types/doctrine": {
-      "version": "0.0.3",
-      "resolved": "https://registry.npmjs.org/@types/doctrine/-/doctrine-0.0.3.tgz",
-      "integrity": "sha1-6JLSk8ksnB0/mvcsFaVU+8fgiVo=",
-      "dev": true
-    },
     "@types/events": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz",
@@ -806,45 +784,18 @@
       "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
       "dev": true
     },
-    "array-differ": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz",
-      "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=",
-      "dev": true
-    },
     "array-equal": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz",
       "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=",
       "dev": true
     },
-    "array-union": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
-      "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
-      "dev": true,
-      "requires": {
-        "array-uniq": "^1.0.1"
-      }
-    },
-    "array-uniq": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
-      "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
-      "dev": true
-    },
     "array-unique": {
       "version": "0.3.2",
       "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
       "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
       "dev": true
     },
-    "arrify": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
-      "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
-      "dev": true
-    },
     "asn1": {
       "version": "0.2.4",
       "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
@@ -1291,12 +1242,6 @@
         }
       }
     },
-    "call-me-maybe": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz",
-      "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=",
-      "dev": true
-    },
     "callsites": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -1422,12 +1367,6 @@
       "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
       "dev": true
     },
-    "code-block-writer": {
-      "version": "7.2.2",
-      "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-7.2.2.tgz",
-      "integrity": "sha1-FOwBIN6aZdLMXSFFYdUdFmDd27E=",
-      "dev": true
-    },
     "code-point-at": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
@@ -1736,33 +1675,6 @@
       "integrity": "sha512-xLqpez+Zj9GKSnPWS0WZw1igGocZ+uua8+y+5dDNTT934N3QuY1sp2LkHzwiaYQGz60hMq0pjAshdeXm5VUOEw==",
       "dev": true
     },
-    "dir-glob": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz",
-      "integrity": "sha1-CyBdK2rvmCOMooZZioIE0p0KADQ=",
-      "dev": true,
-      "requires": {
-        "arrify": "^1.0.1",
-        "path-type": "^3.0.0"
-      },
-      "dependencies": {
-        "path-type": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
-          "integrity": "sha1-zvMdyOCho7sNEFwM2Xzzv0f0428=",
-          "dev": true,
-          "requires": {
-            "pify": "^3.0.0"
-          }
-        },
-        "pify": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
-          "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
-          "dev": true
-        }
-      }
-    },
     "docs-ts": {
       "version": "0.2.1",
       "resolved": "https://registry.npmjs.org/docs-ts/-/docs-ts-0.2.1.tgz",
@@ -1869,16 +1781,6 @@
         }
       }
     },
-    "doctrine": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz",
-      "integrity": "sha1-xz2NKQnSIpHhoAejlYBNqLZl/mM=",
-      "dev": true,
-      "requires": {
-        "esutils": "^2.0.2",
-        "isarray": "^1.0.0"
-      }
-    },
     "dom-serializer": {
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz",
@@ -2336,347 +2238,6 @@
       "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
       "dev": true
     },
-    "fast-glob": {
-      "version": "2.2.3",
-      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.3.tgz",
-      "integrity": "sha512-NiX+JXjnx43RzvVFwRWfPKo4U+1BrK5pJPsHQdKMlLoFHrrGktXglQhHliSihWAq+m1z6fHk3uwGHrtRbS9vLA==",
-      "dev": true,
-      "requires": {
-        "@mrmlnc/readdir-enhanced": "^2.2.1",
-        "@nodelib/fs.stat": "^1.0.1",
-        "glob-parent": "^3.1.0",
-        "is-glob": "^4.0.0",
-        "merge2": "^1.2.1",
-        "micromatch": "^3.1.10"
-      },
-      "dependencies": {
-        "arr-diff": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
-          "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
-          "dev": true
-        },
-        "array-unique": {
-          "version": "0.3.2",
-          "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
-          "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
-          "dev": true
-        },
-        "braces": {
-          "version": "2.3.2",
-          "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
-          "integrity": "sha1-WXn9PxTNUxVl5fot8av/8d+u5yk=",
-          "dev": true,
-          "requires": {
-            "arr-flatten": "^1.1.0",
-            "array-unique": "^0.3.2",
-            "extend-shallow": "^2.0.1",
-            "fill-range": "^4.0.0",
-            "isobject": "^3.0.1",
-            "repeat-element": "^1.1.2",
-            "snapdragon": "^0.8.1",
-            "snapdragon-node": "^2.0.1",
-            "split-string": "^3.0.2",
-            "to-regex": "^3.0.1"
-          },
-          "dependencies": {
-            "extend-shallow": {
-              "version": "2.0.1",
-              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-              "dev": true,
-              "requires": {
-                "is-extendable": "^0.1.0"
-              }
-            }
-          }
-        },
-        "debug": {
-          "version": "2.6.9",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-          "dev": true,
-          "requires": {
-            "ms": "2.0.0"
-          }
-        },
-        "expand-brackets": {
-          "version": "2.1.4",
-          "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
-          "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
-          "dev": true,
-          "requires": {
-            "debug": "^2.3.3",
-            "define-property": "^0.2.5",
-            "extend-shallow": "^2.0.1",
-            "posix-character-classes": "^0.1.0",
-            "regex-not": "^1.0.0",
-            "snapdragon": "^0.8.1",
-            "to-regex": "^3.0.1"
-          },
-          "dependencies": {
-            "define-property": {
-              "version": "0.2.5",
-              "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-              "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
-              "dev": true,
-              "requires": {
-                "is-descriptor": "^0.1.0"
-              }
-            },
-            "extend-shallow": {
-              "version": "2.0.1",
-              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-              "dev": true,
-              "requires": {
-                "is-extendable": "^0.1.0"
-              }
-            },
-            "is-accessor-descriptor": {
-              "version": "0.1.6",
-              "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
-              "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
-              "dev": true,
-              "requires": {
-                "kind-of": "^3.0.2"
-              },
-              "dependencies": {
-                "kind-of": {
-                  "version": "3.2.2",
-                  "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                  "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-                  "dev": true,
-                  "requires": {
-                    "is-buffer": "^1.1.5"
-                  }
-                }
-              }
-            },
-            "is-data-descriptor": {
-              "version": "0.1.4",
-              "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
-              "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
-              "dev": true,
-              "requires": {
-                "kind-of": "^3.0.2"
-              },
-              "dependencies": {
-                "kind-of": {
-                  "version": "3.2.2",
-                  "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                  "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-                  "dev": true,
-                  "requires": {
-                    "is-buffer": "^1.1.5"
-                  }
-                }
-              }
-            },
-            "is-descriptor": {
-              "version": "0.1.6",
-              "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
-              "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=",
-              "dev": true,
-              "requires": {
-                "is-accessor-descriptor": "^0.1.6",
-                "is-data-descriptor": "^0.1.4",
-                "kind-of": "^5.0.0"
-              }
-            },
-            "kind-of": {
-              "version": "5.1.0",
-              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
-              "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=",
-              "dev": true
-            }
-          }
-        },
-        "extglob": {
-          "version": "2.0.4",
-          "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
-          "integrity": "sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM=",
-          "dev": true,
-          "requires": {
-            "array-unique": "^0.3.2",
-            "define-property": "^1.0.0",
-            "expand-brackets": "^2.1.4",
-            "extend-shallow": "^2.0.1",
-            "fragment-cache": "^0.2.1",
-            "regex-not": "^1.0.0",
-            "snapdragon": "^0.8.1",
-            "to-regex": "^3.0.1"
-          },
-          "dependencies": {
-            "define-property": {
-              "version": "1.0.0",
-              "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
-              "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
-              "dev": true,
-              "requires": {
-                "is-descriptor": "^1.0.0"
-              }
-            },
-            "extend-shallow": {
-              "version": "2.0.1",
-              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-              "dev": true,
-              "requires": {
-                "is-extendable": "^0.1.0"
-              }
-            }
-          }
-        },
-        "fill-range": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
-          "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
-          "dev": true,
-          "requires": {
-            "extend-shallow": "^2.0.1",
-            "is-number": "^3.0.0",
-            "repeat-string": "^1.6.1",
-            "to-regex-range": "^2.1.0"
-          },
-          "dependencies": {
-            "extend-shallow": {
-              "version": "2.0.1",
-              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-              "dev": true,
-              "requires": {
-                "is-extendable": "^0.1.0"
-              }
-            }
-          }
-        },
-        "glob-parent": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
-          "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
-          "dev": true,
-          "requires": {
-            "is-glob": "^3.1.0",
-            "path-dirname": "^1.0.0"
-          },
-          "dependencies": {
-            "is-glob": {
-              "version": "3.1.0",
-              "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
-              "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
-              "dev": true,
-              "requires": {
-                "is-extglob": "^2.1.0"
-              }
-            }
-          }
-        },
-        "is-accessor-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
-          "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=",
-          "dev": true,
-          "requires": {
-            "kind-of": "^6.0.0"
-          }
-        },
-        "is-data-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
-          "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=",
-          "dev": true,
-          "requires": {
-            "kind-of": "^6.0.0"
-          }
-        },
-        "is-descriptor": {
-          "version": "1.0.2",
-          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
-          "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=",
-          "dev": true,
-          "requires": {
-            "is-accessor-descriptor": "^1.0.0",
-            "is-data-descriptor": "^1.0.0",
-            "kind-of": "^6.0.2"
-          }
-        },
-        "is-extglob": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
-          "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
-          "dev": true
-        },
-        "is-glob": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz",
-          "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=",
-          "dev": true,
-          "requires": {
-            "is-extglob": "^2.1.1"
-          }
-        },
-        "is-number": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
-          "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
-          "dev": true,
-          "requires": {
-            "kind-of": "^3.0.2"
-          },
-          "dependencies": {
-            "kind-of": {
-              "version": "3.2.2",
-              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-              "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-              "dev": true,
-              "requires": {
-                "is-buffer": "^1.1.5"
-              }
-            }
-          }
-        },
-        "isobject": {
-          "version": "3.0.1",
-          "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
-          "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
-          "dev": true
-        },
-        "kind-of": {
-          "version": "6.0.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
-          "integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE=",
-          "dev": true
-        },
-        "micromatch": {
-          "version": "3.1.10",
-          "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
-          "integrity": "sha1-cIWbyVyYQJUvNZoGij/En57PrCM=",
-          "dev": true,
-          "requires": {
-            "arr-diff": "^4.0.0",
-            "array-unique": "^0.3.2",
-            "braces": "^2.3.1",
-            "define-property": "^2.0.2",
-            "extend-shallow": "^3.0.2",
-            "extglob": "^2.0.4",
-            "fragment-cache": "^0.2.1",
-            "kind-of": "^6.0.2",
-            "nanomatch": "^1.2.9",
-            "object.pick": "^1.3.0",
-            "regex-not": "^1.0.0",
-            "snapdragon": "^0.8.1",
-            "to-regex": "^3.0.2"
-          }
-        },
-        "ms": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-          "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
-          "dev": true
-        }
-      }
-    },
     "fast-json-stable-stringify": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
@@ -2819,8 +2380,7 @@
         "ansi-regex": {
           "version": "2.1.1",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "aproba": {
           "version": "1.2.0",
@@ -2841,14 +2401,12 @@
         "balanced-match": {
           "version": "1.0.0",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "brace-expansion": {
           "version": "1.1.11",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "balanced-match": "^1.0.0",
             "concat-map": "0.0.1"
@@ -2863,20 +2421,17 @@
         "code-point-at": {
           "version": "1.1.0",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "concat-map": {
           "version": "0.0.1",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "console-control-strings": {
           "version": "1.1.0",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "core-util-is": {
           "version": "1.0.2",
@@ -2993,8 +2548,7 @@
         "inherits": {
           "version": "2.0.3",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "ini": {
           "version": "1.3.5",
@@ -3006,7 +2560,6 @@
           "version": "1.0.0",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "number-is-nan": "^1.0.0"
           }
@@ -3021,7 +2574,6 @@
           "version": "3.0.4",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "brace-expansion": "^1.1.7"
           }
@@ -3029,14 +2581,12 @@
         "minimist": {
           "version": "0.0.8",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "minipass": {
           "version": "2.3.5",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "safe-buffer": "^5.1.2",
             "yallist": "^3.0.0"
@@ -3055,7 +2605,6 @@
           "version": "0.5.1",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "minimist": "0.0.8"
           }
@@ -3136,8 +2685,7 @@
         "number-is-nan": {
           "version": "1.0.1",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "object-assign": {
           "version": "4.1.1",
@@ -3149,7 +2697,6 @@
           "version": "1.4.0",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "wrappy": "1"
           }
@@ -3235,8 +2782,7 @@
         "safe-buffer": {
           "version": "5.1.2",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "safer-buffer": {
           "version": "2.1.2",
@@ -3272,7 +2818,6 @@
           "version": "1.0.2",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "code-point-at": "^1.0.0",
             "is-fullwidth-code-point": "^1.0.0",
@@ -3292,7 +2837,6 @@
           "version": "3.0.1",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "ansi-regex": "^2.0.0"
           }
@@ -3336,14 +2880,12 @@
         "wrappy": {
           "version": "1.0.2",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "yallist": {
           "version": "3.0.3",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         }
       }
     },
@@ -3406,55 +2948,12 @@
         "is-glob": "^4.0.1"
       }
     },
-    "glob-to-regexp": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz",
-      "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=",
-      "dev": true
-    },
     "globals": {
       "version": "11.12.0",
       "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
       "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
       "dev": true
     },
-    "globby": {
-      "version": "8.0.1",
-      "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.1.tgz",
-      "integrity": "sha512-oMrYrJERnKBLXNLVTqhm3vPEdJ/b2ZE28xN4YARiix1NOIOBPEpOUnm844K1iu/BkphCaf2WNFwMszv8Soi1pw==",
-      "dev": true,
-      "requires": {
-        "array-union": "^1.0.1",
-        "dir-glob": "^2.0.0",
-        "fast-glob": "^2.0.2",
-        "glob": "^7.1.2",
-        "ignore": "^3.3.5",
-        "pify": "^3.0.0",
-        "slash": "^1.0.0"
-      },
-      "dependencies": {
-        "glob": {
-          "version": "7.1.3",
-          "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
-          "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
-          "dev": true,
-          "requires": {
-            "fs.realpath": "^1.0.0",
-            "inflight": "^1.0.4",
-            "inherits": "2",
-            "minimatch": "^3.0.4",
-            "once": "^1.3.0",
-            "path-is-absolute": "^1.0.0"
-          }
-        },
-        "pify": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
-          "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
-          "dev": true
-        }
-      }
-    },
     "graceful-fs": {
       "version": "4.1.11",
       "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
@@ -3509,9 +3008,9 @@
       }
     },
     "handlebars": {
-      "version": "4.4.2",
-      "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.4.2.tgz",
-      "integrity": "sha512-cIv17+GhL8pHHnRJzGu2wwcthL5sb8uDKBHvZ2Dtu5s1YNt0ljbzKbamnc+gr69y7bzwQiBdr5+hOpRd5pnOdg==",
+      "version": "4.5.3",
+      "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz",
+      "integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==",
       "dev": true,
       "requires": {
         "neo-async": "^2.6.0",
@@ -3689,12 +3188,6 @@
         "safer-buffer": ">= 2.1.2 < 3"
       }
     },
-    "ignore": {
-      "version": "3.3.10",
-      "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz",
-      "integrity": "sha1-Cpf7h2mG6AgcYxFg+PnziRV/AEM=",
-      "dev": true
-    },
     "import-local": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz",
@@ -5267,18 +4760,6 @@
       "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
       "dev": true
     },
-    "multimatch": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz",
-      "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=",
-      "dev": true,
-      "requires": {
-        "array-differ": "^1.0.0",
-        "array-union": "^1.0.1",
-        "arrify": "^1.0.0",
-        "minimatch": "^3.0.0"
-      }
-    },
     "nan": {
       "version": "2.14.0",
       "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
@@ -5665,12 +5146,6 @@
       "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
       "dev": true
     },
-    "path-dirname": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
-      "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=",
-      "dev": true
-    },
     "path-exists": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
@@ -6263,12 +5738,6 @@
       "integrity": "sha512-N+z4pHB4AmUv0SjveWRd6q1Nj5w62m5jodv+GD8lvmbY/83T/rpbJGZOnK5T149OldDj4Db07BSv9xY4K6NTPQ==",
       "dev": true
     },
-    "slash": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
-      "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
-      "dev": true
-    },
     "snapdragon": {
       "version": "0.8.2",
       "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
@@ -7029,67 +6498,6 @@
         }
       }
     },
-    "ts-simple-ast": {
-      "version": "17.1.1",
-      "resolved": "https://registry.npmjs.org/ts-simple-ast/-/ts-simple-ast-17.1.1.tgz",
-      "integrity": "sha1-7NbQDMMdMOufuo+pFJ1y2fodor8=",
-      "dev": true,
-      "requires": {
-        "@dsherret/to-absolute-glob": "^2.0.2",
-        "code-block-writer": "^7.2.2",
-        "fs-extra": "^7.0.0",
-        "glob-parent": "^3.1.0",
-        "globby": "^8.0.1",
-        "is-negated-glob": "^1.0.0",
-        "multimatch": "^2.1.0",
-        "tslib": "^1.9.0",
-        "typescript": "^3.0.1"
-      },
-      "dependencies": {
-        "fs-extra": {
-          "version": "7.0.0",
-          "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.0.tgz",
-          "integrity": "sha512-EglNDLRpmaTWiD/qraZn6HREAEAHJcJOmxNEYwq6xeMKnVMAy3GUcFB+wXt2C6k4CNvB/mP1y/U3dzvKKj5OtQ==",
-          "dev": true,
-          "requires": {
-            "graceful-fs": "^4.1.2",
-            "jsonfile": "^4.0.0",
-            "universalify": "^0.1.0"
-          }
-        },
-        "glob-parent": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
-          "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
-          "dev": true,
-          "requires": {
-            "is-glob": "^3.1.0",
-            "path-dirname": "^1.0.0"
-          }
-        },
-        "is-extglob": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
-          "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
-          "dev": true
-        },
-        "is-glob": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
-          "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
-          "dev": true,
-          "requires": {
-            "is-extglob": "^2.1.0"
-          }
-        },
-        "typescript": {
-          "version": "3.5.3",
-          "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.3.tgz",
-          "integrity": "sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==",
-          "dev": true
-        }
-      }
-    },
     "tslib": {
       "version": "1.9.0",
       "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz",
@@ -7266,20 +6674,20 @@
       "dev": true
     },
     "uglify-js": {
-      "version": "3.6.0",
-      "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz",
-      "integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==",
+      "version": "3.7.0",
+      "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.7.0.tgz",
+      "integrity": "sha512-PC/ee458NEMITe1OufAjal65i6lB58R1HWMRcxwvdz1UopW0DYqlRL3xdu3IcTvTXsB02CRHykidkTRL+A3hQA==",
       "dev": true,
       "optional": true,
       "requires": {
-        "commander": "~2.20.0",
+        "commander": "~2.20.3",
         "source-map": "~0.6.1"
       },
       "dependencies": {
         "commander": {
-          "version": "2.20.1",
-          "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.1.tgz",
-          "integrity": "sha512-cCuLsMhJeWQ/ZpsFTbE765kvVfoeSddc4nU3up4fV+fDBcfUXnbITJ+JzhkdjzOqhURjZgujxaioam4RM9yGUg==",
+          "version": "2.20.3",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+          "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
           "dev": true,
           "optional": true
         },
diff --git a/package.json b/package.json
index eb37ca78..1ab6eb2a 100644
--- a/package.json
+++ b/package.json
@@ -37,26 +37,20 @@
   "homepage": "https://github.com/gcanti/fp-ts",
   "devDependencies": {
     "@types/benchmark": "^1.0.31",
-    "@types/doctrine": "0.0.3",
-    "@types/glob": "^7.1.1",
     "@types/jest": "22.2.2",
     "@types/node": "^12.6.8",
     "@types/prettier": "1.10.0",
     "benchmark": "2.1.4",
-    "chalk": "2.2.0",
     "docs-ts": "^0.2.1",
     "doctoc": "^1.4.0",
-    "doctrine": "2.0.0",
     "dtslint": "github:gcanti/dtslint",
     "fast-check": "^1.12.1",
-    "glob": "^7.1.3",
     "jest": "^24.8.0",
     "mocha": "^5.2.0",
     "prettier": "^1.19.1",
     "rimraf": "2.6.2",
     "ts-jest": "^24.0.2",
     "ts-node": "^8.0.2",
-    "ts-simple-ast": "17.1.1",
     "tslint": "5.11.0",
     "tslint-config-standard": "8.0.1",
     "typescript": "^3.7.2"
diff --git a/src/ReaderTask.ts b/src/ReaderTask.ts
new file mode 100644
index 00000000..ec4dc0a1
--- /dev/null
+++ b/src/ReaderTask.ts
@@ -0,0 +1,148 @@
+import { IO } from './IO'
+import { Monad2 } from './Monad'
+import { MonadTask2 } from './MonadTask'
+import { Monoid } from './Monoid'
+import { pipeable } from './pipeable'
+import { getSemigroup as getReaderSemigroup, Reader } from './Reader'
+import { getReaderM } from './ReaderT'
+import { Semigroup } from './Semigroup'
+import * as TA from './Task'
+
+import Task = TA.Task
+
+const T = getReaderM(TA.task)
+
+declare module './HKT' {
+  interface URItoKind2<E, A> {
+    ReaderTask: ReaderTask<E, A>
+  }
+}
+
+/**
+ * @since 2.3.0
+ */
+export const URI = 'ReaderTask'
+
+/**
+ * @since 2.3.0
+ */
+export type URI = typeof URI
+
+/**
+ * @since 2.3.0
+ */
+export interface ReaderTask<R, A> {
+  (r: R): Task<A>
+}
+
+/**
+ * @since 2.3.0
+ */
+export const fromTask: <R, A>(ma: Task<A>) => ReaderTask<R, A> = T.fromM
+
+/**
+ * @since 2.3.0
+ */
+export const fromReader: <R, A = never>(ma: Reader<R, A>) => ReaderTask<R, A> = T.fromReader
+
+/**
+ * @since 2.3.0
+ */
+export function fromIO<R, A>(ma: IO<A>): ReaderTask<R, A> {
+  return fromTask(TA.fromIO(ma))
+}
+
+/**
+ * @since 2.3.0
+ */
+export const of: <R, A>(a: A) => ReaderTask<R, A> = T.of
+
+/**
+ * @since 2.3.0
+ */
+export function getSemigroup<R, A>(S: Semigroup<A>): Semigroup<ReaderTask<R, A>> {
+  return getReaderSemigroup(TA.getSemigroup<A>(S))
+}
+
+/**
+ * @since 2.3.0
+ */
+export function getMonoid<R, A>(M: Monoid<A>): Monoid<ReaderTask<R, A>> {
+  return {
+    concat: getSemigroup<R, A>(M).concat,
+    empty: of(M.empty)
+  }
+}
+
+/**
+ * @since 2.3.0
+ */
+export const ask: <R>() => ReaderTask<R, R> = T.ask
+
+/**
+ * @since 2.3.0
+ */
+export const asks: <R, A = never>(f: (r: R) => A) => ReaderTask<R, A> = T.asks
+
+/**
+ * @since 2.3.0
+ */
+export function local<Q, R>(f: (f: Q) => R): <E, A>(ma: ReaderTask<R, A>) => ReaderTask<Q, A> {
+  return ma => T.local(ma, f)
+}
+
+/**
+ * @since 2.3.0
+ */
+
+export const readerTask: Monad2<URI> & MonadTask2<URI> = {
+  URI,
+  map: T.map,
+  of,
+  ap: T.ap,
+  chain: T.chain,
+  fromIO,
+  fromTask
+}
+
+/**
+ * Like `readerTask` but `ap` is sequential
+ * @since 2.3.0
+ */
+export const readerTaskSeq: typeof readerTask = {
+  ...readerTask,
+  ap: (mab, ma) => T.chain(mab, f => T.map(ma, f))
+}
+
+const { ap, apFirst, apSecond, chain, chainFirst, flatten, map } = pipeable(readerTask)
+
+export {
+  /**
+   * @since 2.3.0
+   */
+  ap,
+  /**
+   * @since 2.3.0
+   */
+  apFirst,
+  /**
+   * @since 2.3.0
+   */
+  apSecond,
+  /**
+   * @since 2.3.0
+   */
+  chain,
+  /**
+   * @since 2.3.0
+   */
+  chainFirst,
+  /**
+   * @since 2.3.0
+   */
+  flatten,
+  /**
+   * @since 2.3.0
+   */
+  map
+}
diff --git a/src/ReaderTaskEither.ts b/src/ReaderTaskEither.ts
index 6bc92380..7df27555 100644
--- a/src/ReaderTaskEither.ts
+++ b/src/ReaderTaskEither.ts
@@ -1,11 +1,11 @@
-import { Alt3 } from './Alt'
-import { Bifunctor3 } from './Bifunctor'
+import { Alt3, Alt3C } from './Alt'
+import { Bifunctor3, Bifunctor3C } from './Bifunctor'
 import { Either } from './Either'
 import { IO } from './IO'
 import { IOEither } from './IOEither'
-import { Monad3 } from './Monad'
-import { MonadTask3 } from './MonadTask'
-import { MonadThrow3 } from './MonadThrow'
+import { Monad3, Monad3C } from './Monad'
+import { MonadTask3, MonadTask3C } from './MonadTask'
+import { MonadThrow3, MonadThrow3C } from './MonadThrow'
 import { Monoid } from './Monoid'
 import { pipe, pipeable } from './pipeable'
 import { getSemigroup as getReaderSemigroup, Reader } from './Reader'
@@ -16,6 +16,8 @@ import { Task } from './Task'
 import * as TE from './TaskEither'
 
 import TaskEither = TE.TaskEither
+import { readerTask } from './ReaderTask'
+import { getValidationM } from './ValidationT'
 
 const T = getReaderM(TE.taskEither)
 
@@ -224,6 +226,25 @@ export function bracket<R, E, A, B>(
     )
 }
 
+/**
+ * @since 2.3.0
+ */
+export function getReaderTaskValidation<E>(
+  S: Semigroup<E>
+): Monad3C<URI, E> & Bifunctor3C<URI, E> & Alt3C<URI, E> & MonadTask3C<URI, E> & MonadThrow3C<URI, E> {
+  const T = getValidationM(S, readerTask)
+  return {
+    URI,
+    _E: undefined as any,
+    fromIO: rightIO,
+    fromTask: rightTask,
+    throwError: left,
+    bimap: (ma, f, g) => e => TE.taskEither.bimap(ma(e), f, g),
+    mapLeft: (ma, f) => e => TE.taskEither.mapLeft(ma(e), f),
+    ...T
+  }
+}
+
 /**
  * @since 2.0.0
  */
diff --git a/src/index.ts b/src/index.ts
index 10948524..555546fe 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -63,6 +63,7 @@ import * as random from './Random'
 import * as reader from './Reader'
 import * as readerEither from './ReaderEither'
 import * as readerT from './ReaderT'
+import * as readerTask from './ReaderTask'
 import * as readerTaskEither from './ReaderTaskEither'
 import * as record from './Record'
 import * as ring from './Ring'
@@ -349,6 +350,10 @@ export {
    * @since 2.0.0
    */
   readerTaskEither,
+  /**
+   * @since 2.3.0
+   */
+  readerTask,
   /**
    * @since 2.0.0
    */


Test patch:
diff --git a/test/ReaderTask.ts b/test/ReaderTask.ts
new file mode 100644
index 00000000..fd4ef25a
--- /dev/null
+++ b/test/ReaderTask.ts
@@ -0,0 +1,120 @@
+import * as assert from 'assert'
+import { array } from '../src/Array'
+import { pipe } from '../src/pipeable'
+import { reader } from '../src/Reader'
+import * as _ from '../src/ReaderTask'
+import { task } from '../src/Task'
+import { monoidString } from '../src/Monoid'
+import { semigroupString } from '../src/Semigroup'
+
+describe('ReaderTask', () => {
+  describe('Monad', () => {
+    it('map', async () => {
+      const double = (n: number): number => n * 2
+
+      const x = await _.readerTask.map(_.of(1), double)({})()
+      assert.deepStrictEqual(x, 2)
+    })
+
+    it('ap', async () => {
+      const double = (n: number): number => n * 2
+      const mab = _.of(double)
+      const ma = _.of(1)
+      const x = await _.readerTask.ap(mab, ma)({})()
+      assert.deepStrictEqual(x, 2)
+    })
+
+    it('chain', async () => {
+      const f = (a: string) => _.of(a.length)
+      const e1 = await _.readerTask.chain(_.of('foo'), f)({})()
+      assert.deepStrictEqual(e1, 3)
+    })
+
+    describe('readerTaskSeq', () => {
+      it('chain ', async () => {
+        const f = (a: string) => _.of(a.length)
+        const e1 = await _.readerTaskSeq.chain(_.of('foo'), f)({})()
+        assert.deepStrictEqual(e1, 3)
+      })
+    })
+  })
+
+  it('ask', async () => {
+    const e = await _.ask<number>()(1)()
+    return assert.deepStrictEqual(e, 1)
+  })
+
+  it('asks', async () => {
+    const e = await _.asks((s: string) => s.length)('foo')()
+    return assert.deepStrictEqual(e, 3)
+  })
+
+  it('local', async () => {
+    const len = (s: string): number => s.length
+    const e = await pipe(
+      _.asks((n: number) => n + 1),
+      _.local(len)
+    )('aaa')()
+    assert.deepStrictEqual(e, 4)
+  })
+
+  it('fromTask', async () => {
+    const e = await _.fromTask(task.of(1))({})()
+    assert.deepStrictEqual(e, 1)
+  })
+
+  it('fromReader', async () => {
+    const e = await _.fromReader(reader.of(1))({})()
+    assert.deepStrictEqual(e, 1)
+  })
+
+  it('getSemigroup', async () => {
+    const M = _.getSemigroup(semigroupString)
+    const e = await M.concat(_.of('a'), _.of('b'))({})()
+    assert.strictEqual(e, 'ab')
+  })
+
+  it('getMonoid', async () => {
+    const M = _.getMonoid(monoidString)
+    const e = await M.concat(_.of('a'), M.empty)({})()
+    assert.strictEqual(e, 'a')
+    const e2 = await M.concat(M.empty, _.of('b'))({})()
+    assert.strictEqual(e2, 'b')
+    const e3 = await M.concat(_.of('a'), _.of('b'))({})()
+    assert.strictEqual(e3, 'ab')
+  })
+
+  it('reader', async () => {
+    const e = await _.fromReader(reader.of(1))({})()
+    assert.deepStrictEqual(e, 1)
+  })
+
+  it('sequence parallel', async () => {
+    const log: Array<string> = []
+    const append = (message: string): _.ReaderTask<{}, number> => _.fromTask(() => Promise.resolve(log.push(message)))
+    const t1 = _.readerTask.chain(append('start 1'), () => append('end 1'))
+    const t2 = _.readerTask.chain(append('start 2'), () => append('end 2'))
+    const sequenceParallel = array.sequence(_.readerTask)
+    const ns = await sequenceParallel([t1, t2])({})()
+    assert.deepStrictEqual(ns, [3, 4])
+    assert.deepStrictEqual(log, ['start 1', 'start 2', 'end 1', 'end 2'])
+  })
+
+  it('sequence series', async () => {
+    const log: Array<string> = []
+    const append = (message: string): _.ReaderTask<{}, number> => _.fromTask(() => Promise.resolve(log.push(message)))
+    const t1 = _.readerTask.chain(append('start 1'), () => append('end 1'))
+    const t2 = _.readerTask.chain(append('start 2'), () => append('end 2'))
+    const sequenceSeries = array.sequence(_.readerTaskSeq)
+    const ns = await sequenceSeries([t1, t2])({})()
+    assert.deepStrictEqual(ns, [2, 4])
+    assert.deepStrictEqual(log, ['start 1', 'end 1', 'start 2', 'end 2'])
+  })
+
+  describe('MonadIO', () => {
+    it('fromIO', async () => {
+      const e = await _.readerTask.fromIO(() => 1)({})()
+      assert.deepStrictEqual(e, 1)
+    })
+  })
+})
diff --git a/test/ReaderTaskEither.ts b/test/ReaderTaskEither.ts
index 89fcb4b2..72c7114f 100644
--- a/test/ReaderTaskEither.ts
+++ b/test/ReaderTaskEither.ts
@@ -7,7 +7,7 @@ import { none, some } from '../src/Option'
 import { pipe } from '../src/pipeable'
 import { reader } from '../src/Reader'
 import * as _ from '../src/ReaderTaskEither'
-import { semigroupSum } from '../src/Semigroup'
+import { semigroupSum, semigroupString } from '../src/Semigroup'
 import { task } from '../src/Task'
 import { taskEither } from '../src/TaskEither'
 import * as RE from '../src/ReaderEither'
@@ -323,6 +323,85 @@ describe('ReaderTaskEither', () => {
     assert.deepStrictEqual(e2, E.right(1))
   })
 
+  describe('getReaderTaskValidation', () => {
+    const RTV = _.getReaderTaskValidation(semigroupString)
+    it('of', async () => {
+      const e = await RTV.of(1)({})()
+      assert.deepStrictEqual(e, E.right(1))
+    })
+
+    it('throwError', async () => {
+      const e = await RTV.throwError('error')({})()
+      assert.deepStrictEqual(e, E.left('error'))
+    })
+
+    it('map', async () => {
+      const double = (n: number): number => n * 2
+      const e1 = await RTV.map(RTV.of(1), double)({})()
+      assert.deepStrictEqual(e1, E.right(2))
+      const e2 = await RTV.map(_.left('a'), double)({})()
+      assert.deepStrictEqual(e2, E.left('a'))
+    })
+
+    it('ap', async () => {
+      const fab = _.left('a')
+      const fa = _.left('b')
+      const e1 = await RTV.ap(fab, fa)({})()
+      assert.deepStrictEqual(e1, E.left('ab'))
+    })
+
+    it('chain', async () => {
+      const e1 = await RTV.chain(_.right(3), a => (a > 2 ? _.right(a) : _.left('b')))({})()
+      assert.deepStrictEqual(e1, E.right(3))
+      const e2 = await RTV.chain(_.right(1), a => (a > 2 ? _.right(a) : _.left('b')))({})()
+      assert.deepStrictEqual(e2, E.left('b'))
+      const e3 = await RTV.chain(_.left('a'), a => (a > 2 ? _.right(a) : _.left('b')))({})()
+      assert.deepStrictEqual(e3, E.left('a'))
+    })
+
+    it('bimap', async () => {
+      const e1 = await RTV.bimap(
+        _.right(3),
+        e => e,
+        v => v
+      )({})()
+      assert.deepStrictEqual(e1, E.right(3))
+      const e2 = await RTV.bimap(
+        _.left('3'),
+        e => e,
+        v => v
+      )({})()
+      assert.deepStrictEqual(e2, E.left('3'))
+    })
+
+    it('mapLeft', async () => {
+      const e1 = await RTV.mapLeft(_.right(3), a => `x${a}`)({})()
+      assert.deepStrictEqual(e1, E.right(3))
+      const e2 = await RTV.mapLeft(_.left('3'), a => `x${a}`)({})()
+      assert.deepStrictEqual(e2, E.left('x3'))
+    })
+
+    it('alt', async () => {
+      const e1 = await RTV.alt(_.right(1), () => _.right(2))({})()
+      assert.deepStrictEqual(e1, E.right(1))
+      const e2 = await RTV.alt(_.left('a'), () => _.right(2))({})()
+      assert.deepStrictEqual(e2, E.right(2))
+      const e3 = await RTV.alt(_.right(1), () => _.left('b'))({})()
+      assert.deepStrictEqual(e3, E.right(1))
+      const e4 = await RTV.alt(_.left('a'), () => _.left('b'))({})()
+      assert.deepStrictEqual(e4, E.left('ab'))
+    })
+
+    it('traverse', async () => {
+      const e1 = await array.traverse(RTV)([1, 2, 3], RTV.of)({})()
+      assert.deepStrictEqual(e1, E.right([1, 2, 3]))
+      const e2 = await array.traverse(RTV)([1, 2, 3], v => RTV.throwError(`${v}`))({})()
+      assert.deepStrictEqual(e2, E.left('123'))
+      const e3 = await array.traverse(RTV)([1, 2, 3], v => (v % 2 === 1 ? RTV.throwError(`${v}`) : RTV.of(v)))({})()
+      assert.deepStrictEqual(e3, E.left('13'))
+    })
+  })
+
   describe('bracket', () => {
     let log: Array<string> = []