diff --git a/LICENCE b/LICENCE
new file mode 100644
--- /dev/null
+++ b/LICENCE
@@ -0,0 +1,30 @@
+Copyright (c) 2021 Tony Morris
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Tony Morris nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/changelog.md b/changelog.md
new file mode 100644
--- /dev/null
+++ b/changelog.md
@@ -0,0 +1,7 @@
+0.0.2
+
+* Widen version bounds
+
+0.0.1
+
+* The initial version of reader.
diff --git a/reader.cabal b/reader.cabal
new file mode 100644
--- /dev/null
+++ b/reader.cabal
@@ -0,0 +1,41 @@
+name:                 reader
+version:              0.0.2
+synopsis:             A reader data type with all the bits
+description:          A reader data type with all the bits
+license:              BSD3
+license-file:         LICENCE
+author:               Tony Morris <ʇǝu˙sıɹɹoɯʇ@ןןǝʞsɐɥ>
+maintainer:           Tony Morris <ʇǝu˙sıɹɹoɯʇ@ןןǝʞsɐɥ>
+copyright:            Copyright (C) 2021-2015 Tony Morris
+category:             Test
+build-type:           Simple
+extra-source-files:   changelog.md
+cabal-version:        >=1.10
+homepage:             https://gitlab.com/tonymorris/reader
+bug-reports:          https://gitlab.com/tonymorris/reader/issues
+tested-with:          GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.3, GHC == 8.6.5, GHC == 9.4.8, GHC == 9.10.1, GHC == 9.12.2
+
+source-repository     head
+  type:               git
+  location:           git@gitlab.com:tonymorris/reader.git
+
+library
+  exposed-modules:    Data.Reader
+                      Data.Reader.Readers
+                      Data.Reader.Reader1
+                      Data.Reader.Reader2
+                      Data.Reader.Reader3
+
+  build-depends:        base >= 4.8 && < 6
+                      , contravariant >= 1 && < 2
+                      , distributive >= 0.5 && < 1
+                      , lens >= 4 && < 6
+                      , mmorph >= 1.1 && < 2
+                      , mtl >= 2.2 && < 3
+                      , profunctors >= 5 && < 6
+                      , transformers >= 0.5 && < 1
+                      , semigroupoids >= 5.3 && < 7
+
+  hs-source-dirs:     src
+  default-language:   Haskell2010
+  ghc-options:        -Wall
diff --git a/src/Data/Reader.hs b/src/Data/Reader.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Reader.hs
@@ -0,0 +1,9 @@
+{-# OPTIONS_GHC -Wall #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Data.Reader( module R ) where
+
+import Data.Reader.Readers as R
+import Data.Reader.Reader1 as R
+import Data.Reader.Reader2 as R
+import Data.Reader.Reader3 as R
diff --git a/src/Data/Reader/Reader1.hs b/src/Data/Reader/Reader1.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Reader/Reader1.hs
@@ -0,0 +1,243 @@
+{-# OPTIONS_GHC -Wall #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+
+module Data.Reader.Reader1(
+  Reader1T(..)
+, Reader1
+, Reader1Lens
+, reader1
+, reader1Lens
+, reader1'
+, star1
+, kleisli1
+) where
+
+import Control.Applicative
+    ( Applicative((<*>), pure), Alternative((<|>), empty) )
+import Control.Arrow
+    ( Kleisli(Kleisli) )
+import Control.Category ( Category(..) )
+import Control.Lens
+    ( LensLike, view, iso, review, over, _Wrapped, Iso, Rewrapped, Wrapped(..) )
+import Control.Monad
+    ( Monad(return, (>>=)), MonadPlus(..) )
+import Control.Monad.State.Class ( MonadState(..) )
+import Control.Monad.Reader.Class ( MonadReader(..) )
+import Control.Monad.Writer.Class ( MonadWriter(..) )
+import Control.Monad.Error.Class ( MonadError(..) )
+import Control.Monad.Cont.Class ( MonadCont(..) )
+import Control.Monad.IO.Class ( MonadIO(..) )
+import Control.Monad.Morph
+    ( MFunctor(..), MMonad(..) )
+import qualified Control.Monad.Reader as Reader(ReaderT(ReaderT))
+import Control.Monad.Trans.Class ( MonadTrans(..) )
+import Data.Functor ( Functor(fmap) )
+import Data.Functor.Alt ( Alt((<!>)) )
+import Data.Functor.Apply ( Apply((<.>), liftF2) )
+import Data.Functor.Bind ( Bind((>>-)) )
+import Data.Functor.Contravariant ( Contravariant(contramap) )
+import Data.Functor.Contravariant.Divisible
+    ( Decidable(..), Divisible(..) )
+import Data.Functor.Identity ( Identity(..) )
+import Data.Functor.Plus ( Plus(..) )
+import Data.Monoid(Monoid(mempty))
+import Data.Profunctor ( Star(Star) )
+import Data.Semigroup ( Semigroup((<>)) )
+
+newtype Reader1T a f b =
+  Reader1T (a -> f b)
+
+instance Reader1T a f b ~ x =>
+  Rewrapped (Reader1T a' f' b') x
+instance Wrapped (Reader1T a f b) where
+  type Unwrapped (Reader1T a f b) =
+    a
+    -> f b
+  _Wrapped' =
+    iso (\(Reader1T x) -> x) Reader1T
+
+type Reader1 a b =
+  Reader1T a Identity b
+
+reader1 ::
+  Iso
+    (Reader1 a b)
+    (Reader1 a' b')
+    (a -> b)
+    (a' -> b')
+reader1 =
+  iso
+    (\r -> runIdentity . view _Wrapped r)
+    (\f -> review _Wrapped (Identity . f))
+
+type Reader1Lens f s t a b =
+  Reader1T a f b
+  -> Reader1T s f t
+
+reader1Lens ::
+  Iso
+    (LensLike f s t a b)
+    (LensLike f' s' t' a' b')
+    (Reader1Lens f s t a b)
+    (Reader1Lens f' s' t' a' b')
+reader1Lens =
+  iso
+    (\k f -> Reader1T (k (view _Wrapped f)))
+    (\k f -> view _Wrapped (k (Reader1T f)))
+
+reader1' ::
+  Iso
+    (Reader.ReaderT a f b)
+    (Reader.ReaderT a' f' b')
+    (Reader1T a f b)
+    (Reader1T a' f' b')
+reader1' =
+  iso
+    (\(Reader.ReaderT k) -> Reader1T k)
+    (\(Reader1T k) -> Reader.ReaderT k)
+
+star1 ::
+  Iso
+    (Star f a b)
+    (Star f' a' b')
+    (Reader1T a f b)
+    (Reader1T a' f' b')
+star1 =
+  iso
+    (\(Star k) -> Reader1T k)
+    (\(Reader1T k) -> Star k)
+
+kleisli1 ::
+  Iso
+    (Kleisli f a b)
+    (Kleisli f' a' b')
+    (Reader1T a f b)
+    (Reader1T a' f' b')
+kleisli1 =
+  iso
+    (\(Kleisli k) -> Reader1T k)
+    (\(Reader1T k) -> Kleisli k)
+
+instance Functor f => Functor (Reader1T a f) where
+  fmap f (Reader1T g) =
+    Reader1T (fmap (fmap f) g)
+
+instance Apply f => Apply (Reader1T a f) where
+  Reader1T f <.> Reader1T a =
+    Reader1T (\x -> f x <.> a x)
+
+instance Applicative f => Applicative (Reader1T a f) where
+  pure =
+    Reader1T . pure . pure
+  Reader1T f <*> Reader1T a =
+    Reader1T (\x -> f x <*> a x)
+
+instance Bind f => Bind (Reader1T a f) where
+  Reader1T a >>- f =
+    Reader1T (\x -> a x >>- \l -> view _Wrapped (f l) x)
+
+instance Monad f => Monad (Reader1T a f) where
+  return =
+    pure
+  Reader1T a >>= f =
+    Reader1T (\x -> a x >>= \l -> view _Wrapped (f l) x)
+
+instance Alt f => Alt (Reader1T a f) where
+  Reader1T x <!> Reader1T y =
+    Reader1T (\a -> x a <!> y a)
+
+instance Alternative f => Alternative (Reader1T a f) where
+  Reader1T x <|> Reader1T y =
+    Reader1T (\a -> x a <|> y a)
+  empty =
+    Reader1T (pure empty)
+
+instance (Alt f, Alternative f) => Plus (Reader1T a f) where
+  zero =
+    empty
+
+instance MonadPlus f => MonadPlus (Reader1T a f) where
+  mzero =
+    empty
+  mplus =
+    (<|>)
+
+instance (Semigroup b, Apply f) => Semigroup (Reader1T a f b) where
+  Reader1T x <> Reader1T y =
+    Reader1T (\a -> liftF2 (<>) (x a) (y a))
+
+instance (Monoid b, Apply f, Applicative f) => Monoid (Reader1T a f b) where
+  mempty =
+    Reader1T (pure (pure mempty))
+
+instance MonadTrans (Reader1T a) where
+  lift =
+    Reader1T . pure
+
+instance MFunctor (Reader1T a) where
+  hoist f =
+    over _Wrapped (f .)
+
+instance MMonad (Reader1T a) where
+  embed f =
+    over _Wrapped (\g a -> view _Wrapped (f (g a)) a)
+
+instance Monad f => MonadReader a (Reader1T a f) where
+  ask =
+    Reader1T pure
+  local f =
+    over _Wrapped (. f)
+  reader f =
+    Reader1T (pure . f)
+
+instance MonadWriter a f => MonadWriter a (Reader1T a f) where
+  writer =
+    lift . writer
+  tell =
+    lift . tell
+  listen =
+    over _Wrapped (listen .)
+  pass =
+    over _Wrapped (pass .)
+
+instance MonadState a f => MonadState a (Reader1T a f) where
+  get =
+    lift get
+  put =
+    lift . put
+  state =
+    lift . state
+
+instance MonadError a f => MonadError a (Reader1T a f) where
+  throwError =
+    lift . throwError
+  catchError m h =
+    Reader1T (\r -> catchError (view _Wrapped m r) (\e -> view _Wrapped (h e) r))
+
+instance MonadCont f => MonadCont (Reader1T a f) where
+  callCC f =
+    Reader1T (\r -> callCC (\ c -> view _Wrapped (f (Reader1T . pure . c)) r))
+
+instance MonadIO f => MonadIO (Reader1T a f) where
+  liftIO =
+    Reader1T . pure . liftIO
+
+instance Contravariant f => Contravariant (Reader1T a f) where
+  contramap f =
+    over _Wrapped (fmap (contramap f))
+
+instance Divisible f => Divisible (Reader1T a f) where
+  divide k (Reader1T f) (Reader1T g) =
+    Reader1T (liftF2 (divide k) f g)
+  conquer =
+    Reader1T (pure conquer)
+
+instance Decidable f => Decidable (Reader1T a f) where
+  lose =
+    Reader1T . pure . lose
+  choose k (Reader1T f) (Reader1T g) =
+    Reader1T (liftF2 (choose k) f g)
diff --git a/src/Data/Reader/Reader2.hs b/src/Data/Reader/Reader2.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Reader/Reader2.hs
@@ -0,0 +1,336 @@
+{-# OPTIONS_GHC -Wall #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+
+module Data.Reader.Reader2(
+  Reader2T(..)
+, Reader2
+, Reader2Lens
+, reader2
+, reader2Lens
+, reader2'
+, star2
+, kleisli2
+) where
+
+import Data.Type.Equality
+import Control.Applicative
+    ( Applicative((<*>), pure), Alternative((<|>), empty) )
+import Control.Arrow
+    ( ArrowZero(..),
+      ArrowPlus(..),
+      Arrow(first, second, arr),
+      (>>>),
+      ArrowApply(..),
+      ArrowChoice(..),
+      ArrowLoop(..),
+      Kleisli(Kleisli) )
+import Control.Category ( Category(..) )
+import Control.Lens
+    ( LensLike, view, iso, review, over, _Wrapped, Iso, Rewrapped, Wrapped(..) )
+import Control.Monad
+    ( Monad(return, (>>=)), sequence, MonadPlus(..), (>=>) )
+import Control.Monad.State.Class ( MonadState(..) )
+import Control.Monad.Reader.Class ( MonadReader(..) )
+import Control.Monad.Writer.Class ( MonadWriter(..) )
+import Control.Monad.Error.Class ( MonadError(..) )
+import Control.Monad.Fix ( MonadFix(..) )
+import Control.Monad.Cont.Class ( MonadCont(..) )
+import Control.Monad.IO.Class ( MonadIO(..) )
+import qualified Control.Monad.Reader as Reader(ReaderT(ReaderT))
+import Data.Distributive ( Distributive(distribute, collect) )
+import Data.Either ( Either(Right, Left), either )
+import Data.Functor ( Functor(fmap) )
+import Data.Functor.Alt ( Alt((<!>)) )
+import Data.Functor.Apply ( Apply((<.>), liftF2) )
+import Data.Functor.Bind ( Bind((>>-)), (->-) )
+import Data.Functor.Contravariant ( Contravariant(contramap) )
+import Data.Functor.Contravariant.Divisible
+    ( Decidable(..), Divisible(..) )
+import Data.Functor.Identity ( Identity(..) )
+import Data.Functor.Plus ( Plus(..) )
+import Data.Monoid(Monoid(mempty))
+import Data.Profunctor
+    ( Choice(..),
+      Profunctor(dimap),
+      Star(Star),
+      Closed(..),
+      Costrong(unfirst),
+      Strong(..),
+      Mapping(..),
+      Cochoice(unright) )
+import Data.Profunctor.Traversing ( Traversing(..) )
+import Data.Semigroup ( Semigroup((<>)) )
+import Data.Semigroupoid ( Semigroupoid(..) )
+import Data.Traversable ( Traversable(traverse) )
+import Data.Tuple ( fst, snd, uncurry )
+
+newtype Reader2T f a b =
+  Reader2T (a -> f b)
+
+instance Reader2T f a b ~ x =>
+  Rewrapped (Reader2T f' a' b') x
+instance Wrapped (Reader2T f a b) where
+  type Unwrapped (Reader2T f a b) =
+    a
+    -> f b
+  _Wrapped' =
+    iso (\(Reader2T x) -> x) Reader2T
+
+type Reader2 a b =
+  Reader2T Identity a b
+
+reader2 ::
+  Iso
+    (Reader2 a b)
+    (Reader2 a' b')
+    (a -> b)
+    (a' -> b')
+reader2 =
+  iso
+    (\r -> runIdentity . view _Wrapped r)
+    (\f -> review _Wrapped (Identity . f))
+
+reader2' ::
+  Iso
+    (Reader.ReaderT a f b)
+    (Reader.ReaderT a' f' b')
+    (Reader2T f a b)
+    (Reader2T f' a' b')
+reader2' =
+  iso
+    (\(Reader.ReaderT k) -> Reader2T k)
+    (\(Reader2T k) -> Reader.ReaderT k)
+
+type Reader2Lens f s t a b =
+  Reader2T f a b
+  -> Reader2T f s t
+
+reader2Lens ::
+  Iso
+    (LensLike f s t a b)
+    (LensLike f' s' t' a' b')
+    (Reader2Lens f s t a b)
+    (Reader2Lens f' s' t' a' b')
+reader2Lens =
+  iso
+    (\k f -> Reader2T (k (view _Wrapped f)))
+    (\k f -> view _Wrapped (k (Reader2T f)))
+
+star2 ::
+  Iso
+    (Star f a b)
+    (Star f' a' b')
+    (Reader2T f a b)
+    (Reader2T f' a' b')
+star2 =
+  iso
+    (\(Star k) -> Reader2T k)
+    (\(Reader2T k) -> Star k)
+
+kleisli2 ::
+  Iso
+    (Kleisli f a b)
+    (Kleisli f' a' b')
+    (Reader2T f a b)
+    (Reader2T f' a' b')
+kleisli2 =
+  iso
+    (\(Kleisli k) -> Reader2T k)
+    (\(Reader2T k) -> Kleisli k)
+
+instance Functor f => Functor (Reader2T f a) where
+  fmap f (Reader2T g) =
+    Reader2T (fmap (fmap f) g)
+
+instance Apply f => Apply (Reader2T f a) where
+  Reader2T f <.> Reader2T a =
+    Reader2T (\x -> f x <.> a x)
+
+instance Applicative f => Applicative (Reader2T f a) where
+  pure =
+    Reader2T . pure . pure
+  Reader2T f <*> Reader2T a =
+    Reader2T (\x -> f x <*> a x)
+
+instance Bind f => Bind (Reader2T f a) where
+  Reader2T a >>- f =
+    Reader2T (\x -> a x >>- \l -> view _Wrapped (f l) x)
+
+instance Monad f => Monad (Reader2T f a) where
+  return =
+    pure
+  Reader2T a >>= f =
+    Reader2T (\x -> a x >>= \l -> view _Wrapped (f l) x)
+
+instance Alt f => Alt (Reader2T f a) where
+  Reader2T x <!> Reader2T y =
+    Reader2T (\a -> x a <!> y a)
+
+instance Alternative f => Alternative (Reader2T f a) where
+  Reader2T x <|> Reader2T y =
+    Reader2T (\a -> x a <|> y a)
+  empty =
+    Reader2T (pure empty)
+
+instance (Alt f, Alternative f) => Plus (Reader2T f a) where
+  zero =
+    empty
+
+instance MonadPlus f => MonadPlus (Reader2T f a) where
+  mzero =
+    empty
+  mplus =
+    (<|>)
+
+instance (Semigroup b, Apply f) => Semigroup (Reader2T f a b) where
+  Reader2T x <> Reader2T y =
+    Reader2T (\a -> liftF2 (<>) (x a) (y a))
+
+instance (Monoid b, Apply f, Applicative f) => Monoid (Reader2T f a b) where
+  mempty =
+    Reader2T (pure (pure mempty))
+
+instance Monad f => MonadReader a (Reader2T f a) where
+  ask =
+    Reader2T pure
+  local f =
+    over _Wrapped (. f)
+  reader f =
+    Reader2T (pure . f)
+
+instance MonadWriter a f => MonadWriter a (Reader2T f a) where
+  writer =
+    Reader2T . pure . writer
+  tell =
+    Reader2T . pure . tell
+  listen =
+    over _Wrapped (listen .)
+  pass =
+    over _Wrapped (pass .)
+
+instance MonadState a f => MonadState a (Reader2T f a) where
+  get =
+    (Reader2T . pure) get
+  put =
+    Reader2T . pure . put
+  state =
+    Reader2T . pure . state
+
+instance MonadError a f => MonadError a (Reader2T f a) where
+  throwError =
+    Reader2T . pure . throwError
+  catchError m h =
+    Reader2T (\r -> catchError (view _Wrapped m r) (\e -> view _Wrapped (h e) r))
+
+instance MonadCont f => MonadCont (Reader2T f a) where
+  callCC f =
+    Reader2T (\r -> callCC (\ c -> view _Wrapped (f (Reader2T . pure . c)) r))
+
+instance MonadIO f => MonadIO (Reader2T f a) where
+  liftIO =
+    Reader2T . pure . liftIO
+
+instance Functor f => Profunctor (Reader2T f) where
+  dimap f g =
+    over _Wrapped (\k -> fmap g . k . f)
+
+instance Functor f => Strong (Reader2T f) where
+  first' =
+    over _Wrapped (\k (a, c) -> fmap (, c) (k a))
+  second' =
+    over _Wrapped (\k (c, a) -> fmap (c ,) (k a))
+
+instance Applicative f => Choice (Reader2T f) where
+  left' =
+    over _Wrapped (\k -> either (fmap Left . k) (pure . Right))
+  right' =
+    over _Wrapped (\k -> either (pure . Left) (fmap Right . k))
+
+instance Applicative f => Traversing (Reader2T f) where
+  traverse' =
+    over _Wrapped traverse
+  wander =
+    over _Wrapped
+
+instance Distributive f => Closed (Reader2T f) where
+  closed =
+    over _Wrapped (\k x -> distribute (k . x))
+
+instance (Applicative f, Distributive f) => Mapping (Reader2T f) where
+  map' =
+    over _Wrapped collect
+  roam f =
+    over _Wrapped (\k s -> fmap (`f` s) (distribute k))
+
+instance MonadFix f => Costrong (Reader2T f) where
+  unfirst =
+    over _Wrapped (\f a -> fmap fst (mfix (\y -> f (a, snd y))))
+
+instance Traversable f => Cochoice (Reader2T f) where
+  unright =
+    over _Wrapped (\f ->
+      let go = either (go . Left) id . sequence . f
+      in  go . Right)
+
+instance Bind f => Semigroupoid (Reader2T f) where
+  o (Reader2T f) (Reader2T g) =
+    Reader2T (g ->- f)
+
+instance Monad f => Category (Reader2T f) where
+  Reader2T f . Reader2T g =
+    Reader2T (g >=> f)
+  id =
+    Reader2T pure
+
+instance Monad f => Arrow (Reader2T f) where
+  arr f =
+    Reader2T (pure . f)
+  first =
+    over _Wrapped (\f (b, d) -> fmap (, d) (f b))
+  second =
+    over _Wrapped (\f (d, b) -> fmap (d ,) (f b))
+
+instance MonadFix f => ArrowLoop (Reader2T f) where
+  loop =
+    unfirst
+
+instance Monad f => ArrowApply (Reader2T f) where
+  app =
+    Reader2T (uncurry (view _Wrapped))
+
+instance Monad f => ArrowChoice (Reader2T f) where
+  left f =
+    f +++ arr id
+  right f =
+    arr id +++ f
+  f +++ g =
+    (f >>> arr Left) ||| (g >>> arr Right)
+  Reader2T f ||| Reader2T g =
+    Reader2T (either f g)
+
+instance MonadPlus f => ArrowZero (Reader2T f) where
+    zeroArrow = Reader2T (pure mzero)
+
+instance MonadPlus f => ArrowPlus (Reader2T f) where
+    Reader2T f <+> Reader2T g = Reader2T (\x -> f x `mplus` g x)
+
+instance Contravariant f => Contravariant (Reader2T f a) where
+  contramap f =
+    over _Wrapped (fmap (contramap f))
+
+instance Divisible f => Divisible (Reader2T f a) where
+  divide k (Reader2T f) (Reader2T g) =
+    Reader2T (liftF2 (divide k) f g)
+  conquer =
+    Reader2T (pure conquer)
+
+instance Decidable f => Decidable (Reader2T f a) where
+  lose =
+    Reader2T . pure . lose
+  choose k (Reader2T f) (Reader2T g) =
+    Reader2T (liftF2 (choose k) f g)
diff --git a/src/Data/Reader/Reader3.hs b/src/Data/Reader/Reader3.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Reader/Reader3.hs
@@ -0,0 +1,136 @@
+{-# OPTIONS_GHC -Wall #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+
+module Data.Reader.Reader3(
+  Reader3T(..)
+, Reader3
+, Reader3Lens
+, reader3
+, reader3Lens
+, reader3'
+, star3
+, kleisli3
+) where
+
+import Data.Type.Equality
+import Control.Applicative
+    ( Applicative(pure), liftA2 )
+import Control.Arrow
+    ( Kleisli(Kleisli) )
+import Control.Category ( Category(..) )
+import Control.Lens
+    ( LensLike, view, iso, review, over, _Wrapped, Iso, Rewrapped, Wrapped(..) )
+import qualified Control.Monad.Reader as Reader(ReaderT(ReaderT))
+import Data.Either ( either )
+import Data.Functor.Apply ( Apply(liftF2) )
+import Data.Functor.Contravariant ( Contravariant(contramap) )
+import Data.Functor.Contravariant.Divisible
+    ( Decidable(..), Divisible(..) )
+import Data.Functor.Identity ( Identity(..) )
+import Data.Monoid(Monoid(mempty, mappend))
+import Data.Profunctor
+    ( Star(Star) )
+import Data.Semigroup ( Semigroup((<>)) )
+import Data.Void ( absurd )
+
+newtype Reader3T f b a =
+  Reader3T (a -> f b)
+
+instance Reader3T f b a ~ x =>
+  Rewrapped (Reader3T f' b' a') x
+instance Wrapped (Reader3T f b a) where
+  type Unwrapped (Reader3T f b a) =
+    a
+    -> f b
+  _Wrapped' =
+    iso (\(Reader3T x) -> x) Reader3T
+
+type Reader3 a b =
+  Reader3T Identity b a
+
+reader3 ::
+  Iso
+    (Reader3 a b)
+    (Reader3 a' b')
+    (a -> b)
+    (a' -> b')
+reader3 =
+  iso
+    (\r -> runIdentity . view _Wrapped r)
+    (\f -> review _Wrapped (Identity . f))
+
+reader3' ::
+  Iso
+    (Reader.ReaderT a f b)
+    (Reader.ReaderT a' f' b')
+    (Reader3T f b a)
+    (Reader3T f' b' a')
+reader3' =
+  iso
+    (\(Reader.ReaderT k) -> Reader3T k)
+    (\(Reader3T k) -> Reader.ReaderT k)
+
+type Reader3Lens f s t a b =
+  Reader3T f b a
+  -> Reader3T f t s
+
+reader3Lens ::
+  Iso
+    (LensLike f s t a b)
+    (LensLike f' s' t' a' b')
+    (Reader3Lens f s t a b)
+    (Reader3Lens f' s' t' a' b')
+reader3Lens =
+  iso
+    (\k f -> Reader3T (k (view _Wrapped f)))
+    (\k f -> view _Wrapped (k (Reader3T f)))
+
+star3 ::
+  Iso
+    (Star f a b)
+    (Star f' a' b')
+    (Reader3T f b a)
+    (Reader3T f' b' a')
+star3 =
+  iso
+    (\(Star k) -> Reader3T k)
+    (\(Reader3T k) -> Star k)
+
+kleisli3 ::
+  Iso
+    (Kleisli f a b)
+    (Kleisli f' a' b')
+    (Reader3T f b a)
+    (Reader3T f' b' a')
+kleisli3 =
+  iso
+    (\(Kleisli k) -> Reader3T k)
+    (\(Reader3T k) -> Kleisli k)
+
+instance Contravariant (Reader3T f b) where
+  contramap f =
+    over _Wrapped (. f)
+
+instance (Monoid b, Applicative f) => Divisible (Reader3T f b) where
+  conquer =
+    Reader3T (pure (pure mempty))
+  divide k (Reader3T f) (Reader3T g) =
+    Reader3T (\a -> let (b, c) = k a in liftA2 mappend (f b) (g c))
+
+instance (Monoid b, Applicative f) => Decidable (Reader3T f b) where
+  lose f =
+    Reader3T (absurd . f)
+  choose k (Reader3T f) (Reader3T g) =
+    Reader3T (either f g . k)
+
+instance (Semigroup b, Apply f) => Semigroup (Reader3T f b a) where
+  Reader3T x <> Reader3T y =
+    Reader3T (\a -> liftF2 (<>) (x a) (y a))
+
+instance (Monoid b, Apply f, Applicative f) => Monoid (Reader3T f b a) where
+  mempty =
+    Reader3T (pure (pure mempty))
diff --git a/src/Data/Reader/Readers.hs b/src/Data/Reader/Readers.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Reader/Readers.hs
@@ -0,0 +1,78 @@
+{-# OPTIONS_GHC -Wall #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Data.Reader.Readers(
+  _Reader1Reader2
+, _Reader2Reader1
+) where
+
+import Control.Lens ( iso, Iso )
+import Data.Reader.Reader1 ( Reader1T(..) )
+import Data.Reader.Reader2 ( Reader2T(..) )
+import Data.Reader.Reader3 ( Reader3T(..) )
+
+_Reader1Reader2 ::
+  Iso
+    (Reader2T f a b)
+    (Reader2T f' a' b')
+    (Reader1T a f b)
+    (Reader1T a' f' b')
+_Reader1Reader2 =
+  iso
+    (\(Reader2T f) -> Reader1T f)
+    (\(Reader1T f) -> Reader2T f)
+
+_Reader1Reader3 ::
+  Iso
+    (Reader3T f b a)
+    (Reader3T f' b' a')
+    (Reader1T a f b)
+    (Reader1T a' f' b')
+_Reader1Reader3 =
+  iso
+    (\(Reader3T f) -> Reader1T f)
+    (\(Reader1T f) -> Reader3T f)
+
+_Reader2Reader1 ::
+  Iso
+    (Reader1T a f b)
+    (Reader1T a' f' b')
+    (Reader2T f a b)
+    (Reader2T f' a' b')
+_Reader2Reader1 =
+  iso
+    (\(Reader1T f) -> Reader2T f)
+    (\(Reader2T f) -> Reader1T f)
+
+_Reader2Reader3 ::
+  Iso
+    (Reader3T f b a)
+    (Reader3T f' b' a')
+    (Reader2T f a b)
+    (Reader2T f' a' b')
+_Reader2Reader3 =
+  iso
+    (\(Reader3T f) -> Reader2T f)
+    (\(Reader2T f) -> Reader3T f)
+
+_Reader3Reader1 ::
+  Iso
+    (Reader1T a f b)
+    (Reader1T a' f' b')
+    (Reader3T f b a)
+    (Reader3T f' b' a')
+_Reader3Reader1 =
+  iso
+    (\(Reader1T f) -> Reader3T f)
+    (\(Reader3T f) -> Reader1T f)
+
+_Reader3Reader2 ::
+  Iso
+    (Reader2T f a b)
+    (Reader2T f' a' b')
+    (Reader3T f b a)
+    (Reader3T f' b' a')
+_Reader3Reader2 =
+  iso
+    (\(Reader2T f) -> Reader3T f)
+    (\(Reader3T f) -> Reader2T f)
