diff --git a/README.md b/README.md
deleted file mode 100644
--- a/README.md
+++ /dev/null
@@ -1,1 +0,0 @@
-# freelude
diff --git a/freelude.cabal b/freelude.cabal
--- a/freelude.cabal
+++ b/freelude.cabal
@@ -1,64 +1,80 @@
-name:                freelude
-version:             0.1.0.1
-synopsis:            A generalisation of the Category->Functor->Applicative->Monad hierarchy and more
-description:
-  This package generalises classes like Category, Functor etc to allow them to be defined on more data types,
-  for example, tuples and sets, whilst still attempting to maintain backward compatability.
+-- This file has been generated from package.yaml by hpack version 0.20.0.
+--
+-- see: https://github.com/sol/hpack
+--
+-- hash: 2d43b77cfc9355a6259d26ff689dca336df814a1980204ab158ceab224787d63
 
-  See the module "Freelude" for more details.
-homepage:            https://github.com/clintonmead/freelude#readme
-license:             BSD3
-license-file:        LICENSE
-author:              Clinton Mead
-maintainer:          clintonmead@gmail.com
-copyright:           Copyright: (c) 2017 Clinton Mead
-category:            Web
-build-type:          Simple
-extra-source-files:  README.md
-cabal-version:       >=1.10
-tested-with:         GHC == 8.2
+name:           freelude
+version:        0.3.1.0
+synopsis:       A generalisation of the Category->Functor->Applicative->Monad hierarchy and more
+description:    This package generalises classes like Category, Functor etc to allow them to be defined on more data types, for example, tuples and sets, whilst still attempting to maintain backward compatability.
+                .
+                See the module "Freelude" for more details.
+category:       Prelude
+homepage:       https://github.com/clintonmead/freelude#readme
+bug-reports:    https://github.com/clintonmead/freelude/issues
+author:         Clinton Mead
+maintainer:     clintonmead@gmail.com
+copyright:      Copyright: (c) 2018 Clinton Mead
+license:        BSD3
+license-file:   LICENSE
+build-type:     Simple
+cabal-version:  >= 1.10
+
+source-repository head
+  type: git
+  location: https://github.com/clintonmead/freelude
+
 library
-  hs-source-dirs:      src
+  hs-source-dirs:
+      src
+  ghc-options: -Wall
+  build-depends:
+      array
+    , base <99
+    , bytestring
+    , containers
+    , indextype
+    , text
+    , transformers
   exposed-modules:
-    Freelude
-    Freelude.FunctionRestrictedFunctor
-    Freelude.Impl.Category
-    Freelude.Impl.CategoryAsMonoid
-    Freelude.Impl.ExoFunctor
-    Freelude.Impl.MonoidAsCategory
-    Freelude.Impl.MakeFunctor
-    Freelude.Impl.RestrictedFunctor
-    Freelude.Impl.ToKind
-  build-depends:       base == 4.10.*, indextype == 0.3.*, containers, transformers, array
-  default-language:    Haskell2010
-  ghc-options: -Wall -fprint-explicit-kinds
+      Freelude
+      Freelude.FunctionRestrictedFunctor
+      Freelude.Impl.Category
+      Freelude.Impl.CategoryAsMonoid
+      Freelude.Impl.ExoFunctor
+      Freelude.Impl.MakeFunctor
+      Freelude.Impl.MonoidAsCategory
+      Freelude.Impl.RestrictedFunctor
+      Freelude.Impl.ToKind
+  other-modules:
+      Paths_freelude
+  default-language: Haskell2010
 
 test-suite test
-  type:                exitcode-stdio-1.0
-  hs-source-dirs:      test, src
-  main-is:             Test.hs
+  type: exitcode-stdio-1.0
+  main-is: DocTest.hs
+  hs-source-dirs:
+      test
+      src
+  build-depends:
+      array
+    , base <99
+    , bytestring
+    , containers
+    , doctest
+    , indextype
+    , text
+    , transformers
   other-modules:
-    Freelude
-    Freelude.FunctionRestrictedFunctor
-    Freelude.Impl.Category
-    Freelude.Impl.CategoryAsMonoid
-    Freelude.Impl.ExoFunctor
-    Freelude.Impl.MonoidAsCategory
-    Freelude.Impl.MakeFunctor
-    Freelude.Impl.RestrictedFunctor
-    Freelude.Impl.ToKind
-  build-depends:       base == 4.10.*, indextype == 0.3.*, containers, transformers, array
-  ghc-options:         -Wall -threaded -rtsopts -with-rtsopts=-N
-  default-language:    Haskell2010
-
-test-suite doctests
-  type:          exitcode-stdio-1.0
-  hs-source-dirs:      test, src
-  ghc-options:   -threaded
-  main-is:       DocTest.hs
-  build-depends: base == 4.10.*, doctest >= 0.8
+      Freelude
+      Freelude.FunctionRestrictedFunctor
+      Freelude.Impl.Category
+      Freelude.Impl.CategoryAsMonoid
+      Freelude.Impl.ExoFunctor
+      Freelude.Impl.MakeFunctor
+      Freelude.Impl.MonoidAsCategory
+      Freelude.Impl.RestrictedFunctor
+      Freelude.Impl.ToKind
+      Paths_freelude
   default-language: Haskell2010
-
-source-repository head
-  type:     git
-  location: https://github.com/clintonmead/freelude
diff --git a/src/Freelude.hs b/src/Freelude.hs
--- a/src/Freelude.hs
+++ b/src/Freelude.hs
@@ -143,6 +143,7 @@
 
 >>> :set -XTypeFamilies
 >>> :set -XFlexibleContexts
+>>> :set -XTypeInType
 >>> fmap (*3) (1,2)
 (3,6)
 
@@ -165,6 +166,18 @@
 Note that both in the case of sets and unboxed arrays, ordinary 'Prelude.Functor' instances
 can not be defined for them as there are constraints on their parameters.
 
+And finally, we can even define functors over monomorphic containers
+like 'ByteString' and 'Text':
+
+>>> Data.Char.toUpper <$> "Hello World"
+"HELLO WORLD"
+
+>>> Data.Char.toUpper <$> (Data.Text.pack "Hello World")
+"HELLO WORLD"
+
+>>> Data.Char.toUpper <$> (Data.Text.Lazy.pack "Hello World")
+"HELLO WORLD"
+
 We also further generalise 'Functor'. Instead of thinking of 'Functor'
 as a function between functions, we think of it as a function between categories.
 So `fmap` can be defined on other categories.
@@ -179,6 +192,17 @@
 
 >>> f_l <*> [Just 3, Nothing]
 [Just 5,Nothing,Just 9,Nothing,Just 7,Nothing]
+
+GHC even doesn't complain when we try to assert the function laws,
+as long as we @AllowAmbiguousTypes@.
+
+>>> :set -XAllowAmbiguousTypes
+>>> :{
+let
+  eqT :: a -> a -> ()
+  eqT _ _ = ()
+  checkLaws x y = (fmap x . fmap y) `eqT` (fmap (x . y))
+:}
 
 == Applicatives
 
diff --git a/src/Freelude/Impl/Category.hs b/src/Freelude/Impl/Category.hs
--- a/src/Freelude/Impl/Category.hs
+++ b/src/Freelude/Impl/Category.hs
@@ -65,6 +65,14 @@
 import Data.Array.IArray (IArray)
 import Data.Array.Unboxed (UArray)
 
+import qualified Data.Text as StrictText
+import qualified Data.Text.Lazy as LazyText
+
+import qualified Data.ByteString as StrictByteString
+import qualified Data.ByteString.Lazy as LazyByteString
+
+import Data.Word (Word8)
+
 type family CategoryT (p :: Type) (a :: Type) (b :: Type) = (f :: Type) | f -> p a b
 type family ExoCategoryT (p :: Type) (a :: Type) (b :: Type) = (f :: Type) | f -> p a b
 type family CategorySrcC' (p :: Type) :: Maybe (Type -> Constraint)
@@ -326,8 +334,6 @@
 type FunctorSrcC p a = FromMaybeConstraintFunc (FunctorSrcC' p) a
 type FunctorDstC p a = FromMaybeConstraintFunc (FunctorDstC' p) a
 
---type FunctorC cat p a b ra rb = (ra ~ FunctorT p a, rb ~ FunctorT p b, CategoryC cat a b, CategoryC cat ra rb, FunctorSrcC p a, FunctorDstC p b)
-
 class Semigroupoid cat => Functor cat p where
   fmap ::
     (ra ~ FunctorT p a, rb ~ FunctorT p b, CategoryC cat a b, CategoryC cat ra rb, FunctorSrcC p a, FunctorDstC p b) =>
@@ -336,8 +342,6 @@
   default fmap ::
     (Lift p, Pure p, ra ~ FunctorT p a, rb ~ FunctorT p b, CategoryC cat a b, CategoryC cat ra rb, FunctorSrcC p a, FunctorDstC p b, cat ~ FunctionP, FunctorSrcC' p ~ 'Nothing, FunctorDstC' p ~ 'Nothing) =>
     CategoryT cat a b -> CategoryT cat ra rb
---    (Applicative p, cat ~ FunctionP, ra ~ FunctorT p a, rb ~ FunctorT p b, CategoryC cat a b, CategoryC cat ra rb, FunctorSrcC' p ~ 'Nothing, FunctorDstC' p ~ 'Nothing) =>
---    CategoryT cat a b -> CategoryT cat ra rb
   fmap f x = liftA2 (const f) (pure x) x
 
 type UnconstrainedFunctor cat p = (Functor cat p, FunctorSrcC' p ~ 'Nothing, FunctorDstC' p ~ 'Nothing)
@@ -567,6 +571,68 @@
 instance Monad (BasicFunctorP First) where
   (>>=) = (Prelude.>>=)
   (>>) = (Prelude.>>)
+
+data StrictOrLazyP = StrictP | LazyP
+
+data TextP (p :: StrictOrLazyP)
+type instance FunctorSrcC' (TextP _) = 'Just ((~) Char)
+type instance FunctorDstC' (TextP _) = 'Just ((~) Char)
+
+type instance FunctorT (TextP 'StrictP) Char = StrictText.Text
+instance Functor FunctionP (TextP 'StrictP) where
+  fmap = StrictText.map
+instance Pure (TextP 'StrictP) where
+  pure = StrictText.singleton
+instance Lift (TextP 'StrictP) where
+  -- Just go to and from lists. Slow but correct
+  -- This can probably be improved
+  liftA2 f x y = StrictText.pack (liftA2 f (StrictText.unpack x) (StrictText.unpack y))
+instance Monad (TextP 'StrictP) where
+  -- Also going through lists. I'm quite sure this can be improved.
+  x >>= f = StrictText.pack (StrictText.unpack x >>= (StrictText.unpack . f))
+
+type instance FunctorT (TextP 'LazyP) Char = LazyText.Text
+instance Functor FunctionP (TextP 'LazyP) where
+  fmap = LazyText.map
+instance Pure (TextP 'LazyP) where
+  pure = LazyText.singleton
+instance Lift (TextP 'LazyP) where
+  -- Just go to and from lists. Slow but correct
+  -- This can probably be improved
+  liftA2 f x y = LazyText.pack (liftA2 f (LazyText.unpack x) (LazyText.unpack y))
+instance Monad (TextP 'LazyP) where
+  -- Also going through lists. I'm quite sure this can be improved.
+  x >>= f = LazyText.pack (LazyText.unpack x >>= (LazyText.unpack . f))
+
+data ByteStringP (p :: StrictOrLazyP)
+type instance FunctorSrcC' (ByteStringP _) = 'Just ((~) Word8)
+type instance FunctorDstC' (ByteStringP _) = 'Just ((~) Word8)
+
+type instance FunctorT (ByteStringP 'StrictP) Word8 = StrictByteString.ByteString
+instance Functor FunctionP (ByteStringP 'StrictP) where
+  fmap = StrictByteString.map
+instance Pure (ByteStringP 'StrictP) where
+  pure = StrictByteString.singleton
+instance Lift (ByteStringP 'StrictP) where
+  -- Just go to and from lists. Slow but correct
+  -- This can probably be improved
+  liftA2 f x y = StrictByteString.pack (liftA2 f (StrictByteString.unpack x) (StrictByteString.unpack y))
+instance Monad (ByteStringP 'StrictP) where
+  -- Also going through lists. I'm quite sure this can be improved.
+  x >>= f = StrictByteString.pack (StrictByteString.unpack x >>= (StrictByteString.unpack . f))
+
+type instance FunctorT (ByteStringP 'LazyP) Word8 = LazyByteString.ByteString
+instance Functor FunctionP (ByteStringP 'LazyP) where
+  fmap = LazyByteString.map
+instance Pure (ByteStringP 'LazyP) where
+  pure = LazyByteString.singleton
+instance Lift (ByteStringP 'LazyP) where
+  -- Just go to and from lists. Slow but correct
+  -- This can probably be improved
+  liftA2 f x y = LazyByteString.pack (liftA2 f (LazyByteString.unpack x) (LazyByteString.unpack y))
+instance Monad (ByteStringP 'LazyP) where
+  -- Also going through lists. I'm quite sure this can be improved.
+  x >>= f = LazyByteString.pack (LazyByteString.unpack x >>= (LazyByteString.unpack . f))
 
 -- Arrays
 
diff --git a/test/Test.hs b/test/Test.hs
deleted file mode 100644
--- a/test/Test.hs
+++ /dev/null
@@ -1,41 +0,0 @@
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE AllowAmbiguousTypes #-}
-{-# LANGUAGE TypeInType #-}
-{-# OPTIONS_GHC -Wno-missing-signatures #-}
-
-module Main where
-
-import Freelude.Impl.Category
-import Freelude.Impl.ExoFunctor
-import Prelude hiding ((.), fmap, pure, (=<<))
-
-main :: IO ()
-main = pure ()
-
-f1 :: (IsSemigroupoid t1 p a2 a3,  IsSemigroupoid t2 p a1 a2, IsSemigroupoid t3 p a1 a3) => t1 -> t2 -> t3
-f1 x y = x . y
-f1' x y = x . y
-
-f2 :: (IsSemigroupoid t1 p a3 a4, IsSemigroupoid t2 p a2 a3, IsSemigroupoid t3 p a1 a2, IsSemigroupoid t4 p a1 a4) => t1 -> t2 -> t3 -> t4
-f2 x y z = x . y . z
-f2' x y z = x . y . z
-
-f3 x y = fmap x . fmap y
-f3' x y = fmap x . fmap y
-
-f4 x y = fmap (x . y)
-f4' x y = fmap (x . y)
-
-g :: a -> a -> a
-g = undefined
-
-f5 x y = g (f3 x y) (f4 x y)
-
-f6 x y = exomap x . exomap y
-f6' x y = exomap x . exomap y
-
-f7 x y = exomap (x . y)
-f7' x y = exomap (x . y)
-
-f8 x y = g (f6 x y) (f7 x y)
