diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -8,3 +8,8 @@
 * 0.1.0.0
   - Initial version with parameterized Semigroup, Monoid, Applicative, Alternative, Monad
   - Added instances for OverlappingWhichReader, DistinctWhichReader, ManyReader, ManyState, and ChangingState
+
+* 0.2.0.0
+  - Renamed Pempty to PEmpty.
+  - Added injective functional dependencies to PEmpty, and PEmpty.
+  - TypeLevel is not exported by default
diff --git a/parameterized.cabal b/parameterized.cabal
--- a/parameterized.cabal
+++ b/parameterized.cabal
@@ -1,5 +1,5 @@
 name:                parameterized
-version:             0.1.0.0
+version:             0.2.0.0
 synopsis:            Extensible records and polymorphic variants.
 description:         Parameterized/indexed monoids and monads using only a single parameter type variable.
 
@@ -25,9 +25,23 @@
                        Parameterized.Control.Monad.Trans.Reader
                        Parameterized.Control.Monad.Trans.State.Strict
   build-depends:       base >= 4.7 && < 5
-                     , data-diverse >= 1.2.0.2
+                     , data-diverse >= 1.2.0.3
                      , transformers >= 0.5.2.0
   ghc-options:         -Wall
+  default-language:    Haskell2010
+
+test-suite parameterized-test
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      test
+  main-is:             Spec.hs
+  other-modules:       Parameterized.Control.Monad.Trans.Reader.ReaderSpec
+                       Parameterized.Control.Monad.Trans.State.Strict.StateSpec
+  build-depends:       base
+                     , parameterized
+                     , hspec >= 2
+                     , data-diverse >= 1.2.0.3
+                     , transformers >= 0.5.2.0
+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N -Wall
   default-language:    Haskell2010
 
 source-repository head
diff --git a/src/Parameterized/Control/Applicative.hs b/src/Parameterized/Control/Applicative.hs
--- a/src/Parameterized/Control/Applicative.hs
+++ b/src/Parameterized/Control/Applicative.hs
@@ -5,8 +5,7 @@
 {-# LANGUAGE PolyKinds #-}
 
 module Parameterized.Control.Applicative
-    ( module Parameterized.TypeLevel
-    , PPointed(..)
+    ( PPointed(..)
     , PApplicative(..)
     , (&<*>)
     , (&*>)
@@ -20,7 +19,6 @@
     ) where
 
 import Data.Kind
-import Parameterized.TypeLevel
 
 -- | Parameterized version of 'pure' in 'Applicative'
 -- An instance of this should create a parameterized unary type
@@ -71,7 +69,7 @@
 -- | Parameterized version of empty in 'Alternative'.
 -- An instance of this should create a parameterized unary type
 -- where the parameter is an identity in respect to 'pappend'
-class PEmpty (m :: k -> Type -> Type) (id :: k) where
+class PEmpty (m :: k -> Type -> Type) (id :: k) | m -> id where
     -- | The identity of '&<|>'
     pempty :: m id a
 
diff --git a/src/Parameterized/Control/Monad.hs b/src/Parameterized/Control/Monad.hs
--- a/src/Parameterized/Control/Monad.hs
+++ b/src/Parameterized/Control/Monad.hs
@@ -15,7 +15,6 @@
     ) where
 
 import Data.Kind
-import Parameterized.TypeLevel
 import Parameterized.Control.Applicative
 
 -- | Parameterized version of Monad.
diff --git a/src/Parameterized/Control/Monad/Trans/Reader.hs b/src/Parameterized/Control/Monad/Trans/Reader.hs
--- a/src/Parameterized/Control/Monad/Trans/Reader.hs
+++ b/src/Parameterized/Control/Monad/Trans/Reader.hs
@@ -63,6 +63,10 @@
 -- | Given a Reader that accepts @Which a@, and another Reader that accepts @Which b@
 -- make a reader that accepts @Which (Append a b)@ and only run one of the readers for the correct Which type,
 -- with a compile-time contraint that the types in @Which a@ are distinct from the type in @Which b@
+-- The advantage of 'DistinctWhichReader' over 'OverlappingWhichReader' is that 'pappend' doesn't
+-- require the inner monad @m@ to be an 'Alternative'.
+-- NB. 'PEmpty' still requires 'Alternative' but you don't need to be an instance of 'PEmpty'
+-- (analogous to Semigroup)
 newtype DistinctWhichReader m r a = DistinctWhichReader
     { runDistinctWhichReader :: ReaderT r m a
     } deriving ( G.Generic
diff --git a/src/Parameterized/Control/Monad/Trans/State/Strict.hs b/src/Parameterized/Control/Monad/Trans/State/Strict.hs
--- a/src/Parameterized/Control/Monad/Trans/State/Strict.hs
+++ b/src/Parameterized/Control/Monad/Trans/State/Strict.hs
@@ -20,6 +20,7 @@
 import Data.Diverse
 import qualified GHC.Generics as G
 import Parameterized.Control.Monad
+import Parameterized.TypeLevel
 
 -- | Given a ManyState that modifies @Many a@, and another ManyState that modifes @Many b@
 -- make a State that accepts @Many (AppendUnique a b)@
diff --git a/src/Parameterized/Data/Monoid.hs b/src/Parameterized/Data/Monoid.hs
--- a/src/Parameterized/Data/Monoid.hs
+++ b/src/Parameterized/Data/Monoid.hs
@@ -6,19 +6,17 @@
 {-# LANGUAGE PolyKinds #-}
 
 module Parameterized.Data.Monoid
-    ( module Parameterized.TypeLevel
-    , module Parameterized.Data.Semigroup
-    , PMempty(..)
+    ( module Parameterized.Data.Semigroup
+    , PMEmpty(..)
     , PMonoid
     ) where
 
 import Data.Kind
-import Parameterized.TypeLevel
 import Parameterized.Data.Semigroup
 
 -- | Parameterized version of mempty in Monoid.
-class PMempty (n :: k -> Type) (id :: k) where
+class PMEmpty (n :: k -> Type) (id :: k) | n -> id where
     pmempty :: n id
 
 -- | Parameterized version of Monoid.
-type PMonoid n id t u v = (PMempty n id, PSemigroup n t u v)
+type PMonoid n id t u v = (PMEmpty n id, PSemigroup n t u v)
diff --git a/src/Parameterized/TypeLevel.hs b/src/Parameterized/TypeLevel.hs
--- a/src/Parameterized/TypeLevel.hs
+++ b/src/Parameterized/TypeLevel.hs
@@ -6,7 +6,7 @@
 
 module Parameterized.TypeLevel where
 
--- | Get the first type of a type level tuple
+-- | Get the first type of a value level tuple
 -- This is useful for defining a newtype wrapper with a single "parameterized" type,
 -- around a type with many "parameterized" type variables.
 type family At0 t where
@@ -20,7 +20,7 @@
     At0 (x, _, _, _, _, _, _, _, _) = x
     At0 (x, _, _, _, _, _, _, _, _, _) = x
 
--- | Get the second type of a type level tuple
+-- | Get the second type of a value level tuple
 type family At1 t where
     At1 (_, x) = x
     At1 (_, x, _) = x
@@ -32,7 +32,7 @@
     At1 (_, x, _, _, _, _, _, _, _) = x
     At1 (_, x, _, _, _, _, _, _, _, _) = x
 
--- | Get the third type of a type level tuple
+-- | Get the third type of a value level tuple
 type family At2 t where
     At2 (_, _, x) = x
     At2 (_, _, x, _) = x
@@ -43,7 +43,7 @@
     At2 (_, _, x, _, _, _, _, _, _) = x
     At2 (_, _, x, _, _, _, _, _, _, _) = x
 
--- | Get the fourth type of a type level tuple
+-- | Get the fourth type of a value level tuple
 type family At3 t where
     At3 (_, _, _, x) = x
     At3 (_, _, _, x, _) = x
@@ -53,7 +53,7 @@
     At3 (_, _, _, x, _, _, _, _, _) = x
     At3 (_, _, _, x, _, _, _, _, _, _) = x
 
--- | Get the fifth type of a type level tuple
+-- | Get the fifth type of a value level tuple
 type family At4 t where
     At4 (_, _, _, _, x) = x
     At4 (_, _, _, _, x, _) = x
@@ -62,7 +62,7 @@
     At4 (_, _, _, _, x, _, _, _, _) = x
     At4 (_, _, _, _, x, _, _, _, _, _) = x
 
--- | Get the sixth type of a type level tuple
+-- | Get the sixth type of a value level tuple
 type family At5 t where
     At5 (_, _, _, _, _, x) = x
     At5 (_, _, _, _, _, x, _) = x
@@ -70,24 +70,24 @@
     At5 (_, _, _, _, _, x, _, _, _) = x
     At5 (_, _, _, _, _, x, _, _, _, _) = x
 
--- | Get the seventh type of a type level tuple
+-- | Get the seventh type of a value level tuple
 type family At6 t where
     At6 (_, _, _, _, _, _, x) = x
     At6 (_, _, _, _, _, _, x, _) = x
     At6 (_, _, _, _, _, _, x, _, _) = x
     At6 (_, _, _, _, _, _, x, _, _, _) = x
 
--- | Get the eigth type of a type level tuple
+-- | Get the eigth type of a value level tuple
 type family At7 t where
     At7 (_, _, _, _, _, _, _, x) = x
     At7 (_, _, _, _, _, _, _, x, _) = x
     At7 (_, _, _, _, _, _, _, x, _, _) = x
 
--- | Get the nineth type of a type level tuple
+-- | Get the nineth type of a value level tuple
 type family At8 t where
     At8 (_, _, _, _, _, _, _, _, x) = x
     At8 (_, _, _, _, _, _, _, _, x, _) = x
 
--- | Get the tenth type of a type level tuple
+-- | Get the tenth type of a value level tuple
 type family At9 t where
     At9 (_, _, _, _, _, _, _, _, _, x) = x
diff --git a/test/Parameterized/Control/Monad/Trans/Reader/ReaderSpec.hs b/test/Parameterized/Control/Monad/Trans/Reader/ReaderSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Parameterized/Control/Monad/Trans/Reader/ReaderSpec.hs
@@ -0,0 +1,247 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE TypeApplications #-}
+
+module Parameterized.Control.Monad.Trans.Reader.ReaderSpec (main, spec) where
+
+import Control.Applicative
+import Control.Monad.Trans.Reader
+import Parameterized.Control.Monad.Trans.Reader
+import Parameterized.Control.Monad
+import Data.Diverse
+import Data.Semigroup
+import Test.Hspec
+
+
+-- `main` is here so that this module can be run from GHCi on its own.  It is
+-- not needed for automatic spec dicovery.
+main :: IO ()
+main = hspec spec
+
+whichIntMaybeReader :: ReaderT (Which '[Int]) Maybe String
+whichIntMaybeReader = do
+    a <- ask
+    pure . show $ obvious a
+
+whichBoolMaybeReader :: ReaderT (Which '[Bool]) Maybe String
+whichBoolMaybeReader = do
+    a <- ask
+    pure . show $ obvious a
+
+whichStringMaybeReader :: ReaderT (Which '[String]) Maybe String
+whichStringMaybeReader = do
+    a <- ask
+    pure . show $ obvious a
+
+whichIntBoolMaybeReader :: ReaderT (Which '[Int, Bool]) Maybe String
+whichIntBoolMaybeReader = do
+    ay <- ask
+    pure $ switch ay (CaseFunc @Show show)
+
+whichBoolStringMaybeReader :: ReaderT (Which '[Bool, String]) Maybe String
+whichBoolStringMaybeReader = do
+    ay <- ask
+    pure $ switch ay (CaseFunc @Show show)
+
+whichIntStringMaybeReader :: ReaderT (Which '[Int, String]) Maybe String
+whichIntStringMaybeReader = do
+    ay <- ask
+    pure $ switch ay (CaseFunc @Show show)
+
+
+whichIntBoolStringMaybeReader :: ReaderT (Which '[Int, Bool, String]) Maybe String
+whichIntBoolStringMaybeReader = do
+    ay <- ask
+    pure $ switch ay (CaseFunc @Show show)
+
+--------------------------------
+
+whichIntReader :: Reader (Which '[Int]) String
+whichIntReader = do
+    a <- ask
+    pure . show $ obvious a
+
+whichBoolReader :: Reader (Which '[Bool]) String
+whichBoolReader = do
+    a <- ask
+    pure . show $ obvious a
+
+whichStringReader :: Reader (Which '[String]) String
+whichStringReader = do
+    a <- ask
+    pure . show $ obvious a
+
+whichIntBoolReader :: Reader (Which '[Int, Bool]) String
+whichIntBoolReader = do
+    ay <- ask
+    pure $ switch ay (CaseFunc @Show show)
+
+whichIntStringReader :: Reader (Which '[Int, String]) String
+whichIntStringReader = do
+    ay <- ask
+    pure $ switch ay (CaseFunc @Show show)
+
+
+whichIntBoolStringReader :: Reader (Which '[Int, Bool, String]) String
+whichIntBoolStringReader = do
+    ay <- ask
+    pure $ switch ay (CaseFunc @Show show)
+
+--------------------------------
+
+manyIntMaybeReader :: ReaderT (Many '[Int]) Maybe String
+manyIntMaybeReader = do
+    a <- ask
+    let r = fetch @Int a
+    case r of
+        0 -> empty
+        r' -> pure $ show r'
+
+manyBoolMaybeReader :: ReaderT (Many '[Bool]) Maybe String
+manyBoolMaybeReader = do
+    a <- ask
+    let r = fetch @Bool a
+    case r of
+        False -> empty
+        r' -> pure $ show r'
+
+--------------------------------
+
+spec :: Spec
+spec = do
+    describe "Reader (Which a)" $ do
+
+        it "is can maybe read only the types it knows about" $ do
+            runReaderT whichIntMaybeReader (pick (5 :: Int)) `shouldBe` Just "5"
+            runReaderT whichIntBoolMaybeReader (pick (5 :: Int)) `shouldBe` Just "5"
+            runReaderT whichIntBoolStringMaybeReader (pick (5 :: Int)) `shouldBe` Just "5"
+            runReaderT whichBoolMaybeReader (pick False) `shouldBe` Just "False"
+            runReaderT whichIntBoolMaybeReader (pick False) `shouldBe` Just "False"
+            runReaderT whichIntBoolStringMaybeReader (pick False) `shouldBe` Just "False"
+            runReaderT whichStringMaybeReader (pick "foo") `shouldBe` Just "\"foo\""
+            runReaderT whichIntStringMaybeReader (pick "foo") `shouldBe` Just "\"foo\""
+            runReaderT whichIntBoolStringMaybeReader (pick "foo") `shouldBe` Just "\"foo\""
+
+        it "is can read only the types it knows about" $ do
+            runReader whichIntReader (pick (5 :: Int)) `shouldBe` "5"
+            runReader whichIntBoolReader (pick (5 :: Int)) `shouldBe` "5"
+            runReader whichIntBoolStringReader (pick (5 :: Int)) `shouldBe` "5"
+            runReader whichBoolReader (pick False) `shouldBe` "False"
+            runReader whichIntBoolReader (pick False) `shouldBe` "False"
+            runReader whichIntBoolStringReader (pick False) `shouldBe` "False"
+            runReader whichStringReader (pick "foo") `shouldBe` "\"foo\""
+            runReader whichIntStringReader (pick "foo") `shouldBe` "\"foo\""
+            runReader whichIntBoolStringReader (pick "foo") `shouldBe` "\"foo\""
+
+    describe "OverlappingWhichReader" $ do
+        it "pappend with empty doesn't change the type of the parameter" $ do
+            let r1 = OverlappingWhichReader whichIntMaybeReader `pappend` pempty
+                r2 = pempty `pappend` OverlappingWhichReader whichIntMaybeReader
+                -- the "parameter" doesn't change when `pappend` with empty
+                r1' = runOverlappingWhichReader r1 :: ReaderT (Which '[Int]) Maybe String
+                r2' = runOverlappingWhichReader r2 :: ReaderT (Which '[Int]) Maybe String
+            -- functionality unchanged
+            runReaderT r1' (pick (5 :: Int)) `shouldBe` Just "5"
+            runReaderT r2' (pick (5 :: Int)) `shouldBe` Just "5"
+
+        it "it can be pappended to combine distinct readers" $ do
+            let r = OverlappingWhichReader whichIntMaybeReader `pappend`
+                        OverlappingWhichReader whichBoolMaybeReader
+                -- the "parameter" is combined
+                r' = runOverlappingWhichReader r :: ReaderT (Which '[Int, Bool]) Maybe String
+            -- functionality of both readers
+            runReaderT r' (pick (5 :: Int)) `shouldBe` Just "5"
+            runReaderT r' (pick False) `shouldBe` Just "False"
+
+            let r2 = r `pappend` OverlappingWhichReader whichStringMaybeReader
+                -- the "parameter" is combined
+                r2' = runOverlappingWhichReader r2 :: ReaderT (Which '[Int, Bool, String]) Maybe String
+            -- functionality of both readers
+            runReaderT r2' (pick (5 :: Int)) `shouldBe` Just "5"
+            runReaderT r2' (pick False) `shouldBe` Just "False"
+            runReaderT r2' (pick "foo") `shouldBe` Just "\"foo\""
+
+        it "it can be pappended to combine overlapping readers" $ do
+            let r = OverlappingWhichReader whichIntBoolMaybeReader `pappend`
+                        OverlappingWhichReader whichBoolStringMaybeReader
+                -- the "parameter" is combined
+                r' = runOverlappingWhichReader r :: ReaderT (Which '[Int, Bool, String]) Maybe String
+            -- functionality of both readers
+            runReaderT r' (pick (5 :: Int)) `shouldBe` Just "5"
+            runReaderT r' (pick False) `shouldBe` Just "False"
+            runReaderT r' (pick "foo") `shouldBe` Just "\"foo\""
+
+    describe "DistinctWhichReader" $ do
+        it "pappend with empty doesn't change the type of the parameter" $ do
+            let r1 = DistinctWhichReader whichIntMaybeReader `pappend` pempty
+                r2 = pempty `pappend` DistinctWhichReader whichIntMaybeReader
+                -- the "parameter" doesn't change when `pappend` with empty
+                r1' = runDistinctWhichReader r1 :: ReaderT (Which '[Int]) Maybe String
+                r2' = runDistinctWhichReader r2 :: ReaderT (Which '[Int]) Maybe String
+            -- functionality unchanged
+            runReaderT r1' (pick (5 :: Int)) `shouldBe` Just "5"
+            runReaderT r2' (pick (5 :: Int)) `shouldBe` Just "5"
+
+        it "it can be pappended to combine distinct readers" $ do
+            let r = DistinctWhichReader whichIntReader `pappend` DistinctWhichReader whichBoolReader
+                -- the "parameter" is combined
+                r' = runDistinctWhichReader r :: Reader (Which '[Int, Bool]) String
+            -- functionality of both readers
+            runReader r' (pick (5 :: Int)) `shouldBe` "5"
+            runReader r' (pick False) `shouldBe` "False"
+
+            let r2 = r `pappend` DistinctWhichReader whichStringReader
+                -- the "parameter" is combined
+                r2' = runDistinctWhichReader r2 :: Reader (Which '[Int, Bool, String]) String
+            -- functionality of both readers
+            runReader r2' (pick (5 :: Int)) `shouldBe` "5"
+            runReader r2' (pick False) `shouldBe` "False"
+            runReader r2' (pick "foo") `shouldBe` "\"foo\""
+
+    describe "ManyReader" $ do
+        it "pappend with empty doesn't change the type of the parameter" $ do
+            let r1 = ManyReader manyIntMaybeReader `pappend` pempty
+                r2 = pempty `pappend` ManyReader manyIntMaybeReader
+                -- the "parameter" doesn't change when `pappend` with empty
+                r1' = runManyReader r1 :: ReaderT (Many '[Int]) Maybe String
+                r2' = runManyReader r2 :: ReaderT (Many '[Int]) Maybe String
+            -- functionality unchanged
+            runReaderT r1' (single (5 :: Int)) `shouldBe` Just "5"
+            runReaderT r2' (single (5 :: Int)) `shouldBe` Just "5"
+
+        it "it can 'pappend' to combine state runners 'Alternative'ly" $ do
+            let r = ManyReader manyIntMaybeReader `pappend`
+                        ManyReader manyBoolMaybeReader
+                -- the "parameter" is combined
+                r' = runManyReader r :: ReaderT (Many '[Int, Bool]) Maybe String
+            -- functionality of both readers in an Alternative fashion
+            runReaderT r' ( (5 :: Int) ./ True ./ nil) `shouldBe` Just "5"
+            runReaderT r' ( (5 :: Int) ./ False ./ nil) `shouldBe` Just "5"
+            runReaderT r' ( (0 :: Int) ./ True ./ nil) `shouldBe` Just "True"
+            runReaderT r' ( (0 :: Int) ./ False ./ nil) `shouldBe` Nothing
+
+        it "it can 'papply' to combine state runners 'Applicative'ly" $ do
+            let r = (\a b -> a <> "." <> b) <$> ManyReader manyIntMaybeReader &<*>
+                        ManyReader manyBoolMaybeReader
+                -- the "parameter" is combined
+                r' = runManyReader r :: ReaderT (Many '[Int, Bool]) Maybe String
+            -- functionality of both readers in an Alternative fashion
+            runReaderT r' ( (5 :: Int) ./ True ./ nil) `shouldBe` Just "5.True"
+            runReaderT r' ( (5 :: Int) ./ False ./ nil) `shouldBe` Nothing
+            runReaderT r' ( (0 :: Int) ./ True ./ nil) `shouldBe` Nothing
+            runReaderT r' ( (0 :: Int) ./ False ./ nil) `shouldBe` Nothing
+
+
+        it "it can 'pbind' to combine reader runners 'Monad'ically" $ do
+            let r = ManyReader manyIntMaybeReader &>>= \a ->
+                        case a of
+                            "1" -> ManyReader manyBoolMaybeReader
+                            _ -> empty
+                -- the "parameter" is combined
+                r' = runManyReader r :: ReaderT (Many '[Int, Bool]) Maybe String
+            -- functionality of both readers in an Applicative fashion
+            runReaderT r' ( (1 :: Int) ./ True ./ nil) `shouldBe` Just "True"
+            runReaderT r' ( (1 :: Int) ./ False ./ nil) `shouldBe` Nothing
+            runReaderT r' ( (5 :: Int) ./ True ./ nil) `shouldBe` Nothing
+            runReaderT r' ( (5 :: Int) ./ False ./ nil) `shouldBe` Nothing
+            runReaderT r' ( (0 :: Int) ./ True ./ nil) `shouldBe` Nothing
+            runReaderT r' ( (0 :: Int) ./ False ./ nil) `shouldBe` Nothing
diff --git a/test/Parameterized/Control/Monad/Trans/State/Strict/StateSpec.hs b/test/Parameterized/Control/Monad/Trans/State/Strict/StateSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Parameterized/Control/Monad/Trans/State/Strict/StateSpec.hs
@@ -0,0 +1,95 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE TypeApplications #-}
+
+module Parameterized.Control.Monad.Trans.State.Strict.StateSpec (main, spec) where
+
+import Control.Applicative
+import Control.Monad.Trans.State.Strict
+import Parameterized.Control.Monad.Trans.State.Strict
+import Parameterized.Control.Monad
+import Data.Diverse
+import Data.Semigroup
+import Test.Hspec
+
+
+-- `main` is here so that this module can be run from GHCi on its own.  It is
+-- not needed for automatic spec dicovery.
+main :: IO ()
+main = hspec spec
+
+manyIntMaybeState :: StateT (Many '[Int]) Maybe String
+manyIntMaybeState= do
+    s <- get
+    let r = fetch @Int s
+    case r of
+        0 -> empty
+        r' -> do
+           put $ replace @Int s (r' + 1)
+           pure $ show r'
+
+manyBoolMaybeState :: StateT (Many '[Bool]) Maybe String
+manyBoolMaybeState = do
+    s <- get
+    let r = fetch @Bool s
+    case r of
+        False -> empty
+        r' -> do
+            put $ replace @Bool s False
+            pure $ show r'
+
+--------------------------------
+
+spec :: Spec
+spec = do
+
+    describe "ManyState" $ do
+        it "pappend with empty doesn't change the type of the parameter" $ do
+            let r1 = ManyState manyIntMaybeState `pappend` pempty
+                r2 = pempty `pappend` ManyState manyIntMaybeState
+                -- the "parameter" doesn't change when `pappend` with empty
+                r1' = runManyState r1 :: StateT (Many '[Int]) Maybe String
+                r2' = runManyState r2 :: StateT (Many '[Int]) Maybe String
+            -- functionality unchanged
+            runStateT r1' (single (5 :: Int)) `shouldBe` Just ("5", single (6 :: Int))
+            runStateT r2' (single (5 :: Int)) `shouldBe` Just ("5", single (6 :: Int))
+
+        it "it can 'pappend' to combine state runners 'Alternative'ly" $ do
+            let r = ManyState manyIntMaybeState `pappend`
+                        ManyState manyBoolMaybeState
+                -- the "parameter" is combined
+                r' = runManyState r :: StateT (Many '[Int, Bool]) Maybe String
+            -- functionality of both state in an Alternative fashion
+            -- manyIntMaybeState suceeded
+            runStateT r' ( (5 :: Int) ./ True ./ nil) `shouldBe` Just ("5", (6 :: Int) ./ True ./ nil)
+            runStateT r' ( (5 :: Int) ./ False ./ nil) `shouldBe` Just ("5", (6 :: Int) ./ False ./ nil)
+            -- manyBoolMaybeState suceeded
+            runStateT r' ( (0 :: Int) ./ True ./ nil) `shouldBe` Just ("True", (0 :: Int) ./ False ./ nil)
+            -- Both failed
+            runStateT r' ( (0 :: Int) ./ False ./ nil) `shouldBe` Nothing
+
+        it "it can 'papply' to combine state runners 'Applicative'ly" $ do
+            let r = (\a b -> a <> "." <> b) <$> ManyState manyIntMaybeState &<*>
+                        ManyState manyBoolMaybeState
+                -- the "parameter" is combined
+                r' = runManyState r :: StateT (Many '[Int, Bool]) Maybe String
+            -- functionality of both readers in an Applicative fashion
+            runStateT r' ( (5 :: Int) ./ True ./ nil) `shouldBe` Just ("5.True", (6 :: Int) ./ False ./ nil)
+            runStateT r' ( (5 :: Int) ./ False ./ nil) `shouldBe` Nothing
+            runStateT r' ( (0 :: Int) ./ True ./ nil) `shouldBe` Nothing
+            runStateT r' ( (0 :: Int) ./ False ./ nil) `shouldBe` Nothing
+
+
+        it "it can 'pbind' to combine state runners 'Monad'ically" $ do
+            let r = ManyState manyIntMaybeState &>>= \a ->
+                        case a of
+                            "1" -> ManyState manyBoolMaybeState
+                            _ -> empty
+                -- the "parameter" is combined
+                r' = runManyState r :: StateT (Many '[Int, Bool]) Maybe String
+            -- functionality of both readers in an Monad fashion
+            runStateT r' ( (1 :: Int) ./ True ./ nil) `shouldBe` Just ("True", (2 :: Int) ./ False ./ nil)
+            runStateT r' ( (1 :: Int) ./ False ./ nil) `shouldBe` Nothing
+            runStateT r' ( (5 :: Int) ./ True ./ nil) `shouldBe` Nothing
+            runStateT r' ( (5 :: Int) ./ False ./ nil) `shouldBe` Nothing
+            runStateT r' ( (0 :: Int) ./ True ./ nil) `shouldBe` Nothing
+            runStateT r' ( (0 :: Int) ./ False ./ nil) `shouldBe` Nothing
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,1 @@
+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
