diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,5 @@
+# Revision history for TotalMap
+
+## 0.1.0.0  -- YYYY-mm-dd
+
+* First version. Released on an unsuspecting world.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2018 Ed Wastell
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/README.lhs b/README.lhs
new file mode 100644
--- /dev/null
+++ b/README.lhs
@@ -0,0 +1,94 @@
+Total Map
+===============
+
+Often one may have an enum type representing all possible keys of something, and wishes to store some data associated with it. In this case you have two options - use a function or a Map from containers. A function works, but can be difficult to update and has not Eq or Show instances. A map solves this issue, but gives no guarantee that a key has associated data - all functions become partial. This library offers a different way of solving this problem.
+
+A `TotalMap k a` is a total mapping from a key of type `k` to a value of type `a`; each `k` will have exactly one `a`. It permits many instances, including `Show` and `Eq`. 
+
+Example
+------
+
+Let us create and example. We start with some imports and some language pragmas.
+
+```haskell
+{-# LANGUAGE DeriveAnyClass #-}
+{-# LANGUAGE DeriveGeneric #-}
+
+import TotalMap
+
+import Control.Lens
+import Control.Monad (void)
+import Data.Functor.Rep (tabulate)
+import qualified GHC.Generics as GHC (Generic)
+import Generics.SOP
+```
+
+TotalMap uses generics-sop internally, so we require it as an import. We also require some typeclasses introduced by lens.
+
+For our example, we shall create a dummy program for sending out peoples fortunes based on their star sign. We shall create a star sign type.
+
+```haskell
+data StarSign
+  = Aries
+  | Taurus
+  | Gemini
+  | Cancer
+  | Leo
+  | Virgo
+  | Scorpio
+  | Sagittarius
+  | Capricorn
+  | Aquarius
+  | Pisces
+  deriving (Eq, Show, GHC.Generic, Generic)
+```
+
+Note the derivation of both `GHC.Generic` and `Generic`. These are required to guarantee that `StarSign`'s constructors take no imports.
+
+We have a list of people, and we can partition them based on their star sign.
+
+```haskell
+data Date = Date
+  { month :: Int
+  , day :: Int
+  } deriving (Eq, Show)
+
+data Person = Person
+  { name :: String
+  , email :: String
+  , birthDate :: Date
+  } deriving (Eq, Show)
+
+signFromDate :: Date -> StarSign
+signFromDate = undefined
+
+peopleSign :: [Person] -> TotalMap StarSign [Person]
+peopleSign ps = tabulate $ \s -> filter ((==) s . signFromDate . birthDate) ps
+```
+
+We could send people an email with their fortune.
+
+```haskell
+sendFortune :: String -> String -> StarSign -> IO ()
+sendFortune = undefined
+
+sendFortunes :: [Person] -> IO ()
+sendFortunes =
+  void .
+  itraverse (\sign -> mapM_ (\p -> sendFortune (name p) (email p) sign)) .
+  peopleSign
+```
+
+Future
+-----
+
+* Come up with a better example
+* Is Lens necessary. It is useful, but it is a huge dependency.
+
+
+The following is required to make tests compile.
+
+```haskell
+main :: IO ()
+main = return ()
+```
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,94 @@
+Total Map
+===============
+
+Often one may have an enum type representing all possible keys of something, and wishes to store some data associated with it. In this case you have two options - use a function or a Map from containers. A function works, but can be difficult to update and has not Eq or Show instances. A map solves this issue, but gives no guarantee that a key has associated data - all functions become partial. This library offers a different way of solving this problem.
+
+A `TotalMap k a` is a total mapping from a key of type `k` to a value of type `a`; each `k` will have exactly one `a`. It permits many instances, including `Show` and `Eq`. 
+
+Example
+------
+
+Let us create and example. We start with some imports and some language pragmas.
+
+```haskell
+{-# LANGUAGE DeriveAnyClass #-}
+{-# LANGUAGE DeriveGeneric #-}
+
+import TotalMap
+
+import Control.Lens
+import Control.Monad (void)
+import Data.Functor.Rep (tabulate)
+import qualified GHC.Generics as GHC (Generic)
+import Generics.SOP
+```
+
+TotalMap uses generics-sop internally, so we require it as an import. We also require some typeclasses introduced by lens.
+
+For our example, we shall create a dummy program for sending out peoples fortunes based on their star sign. We shall create a star sign type.
+
+```haskell
+data StarSign
+  = Aries
+  | Taurus
+  | Gemini
+  | Cancer
+  | Leo
+  | Virgo
+  | Scorpio
+  | Sagittarius
+  | Capricorn
+  | Aquarius
+  | Pisces
+  deriving (Eq, Show, GHC.Generic, Generic)
+```
+
+Note the derivation of both `GHC.Generic` and `Generic`. These are required to guarantee that `StarSign`'s constructors take no imports.
+
+We have a list of people, and we can partition them based on their star sign.
+
+```haskell
+data Date = Date
+  { month :: Int
+  , day :: Int
+  } deriving (Eq, Show)
+
+data Person = Person
+  { name :: String
+  , email :: String
+  , birthDate :: Date
+  } deriving (Eq, Show)
+
+signFromDate :: Date -> StarSign
+signFromDate = undefined
+
+peopleSign :: [Person] -> TotalMap StarSign [Person]
+peopleSign ps = tabulate $ \s -> filter ((==) s . signFromDate . birthDate) ps
+```
+
+We could send people an email with their fortune.
+
+```haskell
+sendFortune :: String -> String -> StarSign -> IO ()
+sendFortune = undefined
+
+sendFortunes :: [Person] -> IO ()
+sendFortunes =
+  void .
+  itraverse (\sign -> mapM_ (\p -> sendFortune (name p) (email p) sign)) .
+  peopleSign
+```
+
+Future
+-----
+
+* Come up with a better example
+* Is Lens necessary. It is useful, but it is a huge dependency.
+
+
+The following is required to make tests compile.
+
+```haskell
+main :: IO ()
+main = return ()
+```
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/TotalMap.cabal b/TotalMap.cabal
new file mode 100644
--- /dev/null
+++ b/TotalMap.cabal
@@ -0,0 +1,48 @@
+-- Initial TotalMap.cabal generated by cabal init.  For further 
+-- documentation, see http://haskell.org/cabal/users-guide/
+
+name:                TotalMap
+version:             0.1.0.0
+synopsis:            A total map datatype
+description:         Provides a datatype representing a total map using an enum type as keys
+license:             MIT
+license-file:        LICENSE
+author:              Ed Wastell
+maintainer:          ed@wastell.co.uk
+-- copyright:           
+category:            Control
+build-type:          Simple
+extra-source-files:  ChangeLog.md
+  README.lhs
+  README.md
+cabal-version:       >=1.10
+
+source-repository head
+  type: git
+  location: https://github.com/edwardwas/TotalMap
+
+library
+  exposed-modules:     TotalMap
+  -- other-modules:       
+  -- other-extensions:    
+  build-depends:       base >=4.8 && <4.13
+    , generics-sop >= 0.3 && < 0.5
+    , lens >= 4.16 && < 4.20
+    , adjunctions >= 4.4 && < 4.5
+    , distributive >= 0.5 && < 0.7
+  hs-source-dirs:      src
+  default-language:    Haskell2010
+  ghc-options: -Wall
+
+test-suite readme
+  build-depends:       base >=4.8 && <4.13
+    , TotalMap
+    , generics-sop >= 0.3 && < 0.5
+    , lens >= 4.16 && < 4.20
+    , adjunctions >= 4.4 && < 4.5
+    , distributive >= 0.5 && < 0.7
+    , markdown-unlit >= 0.5 && < 0.6
+  main-is: README.lhs
+  ghc-options:    -pgmL markdown-unlit -Wall -Wno-unused-top-binds
+  type:           exitcode-stdio-1.0
+  default-language:    Haskell2010
diff --git a/src/TotalMap.hs b/src/TotalMap.hs
new file mode 100644
--- /dev/null
+++ b/src/TotalMap.hs
@@ -0,0 +1,131 @@
+{-# LANGUAGE FlexibleContexts      #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE GADTs                 #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE PolyKinds             #-}
+{-# LANGUAGE RankNTypes            #-}
+{-# LANGUAGE ScopedTypeVariables   #-}
+{-# LANGUAGE TypeFamilies          #-}
+{-# LANGUAGE UndecidableInstances  #-}
+
+{-|
+Module      : TotalMap
+Description : A total mapp
+Copyright   : (c) Ed Wastell, 2018
+License     : MTL
+Maintainer  : edward@wastell.com
+Stability   : experimental
+
+A total map from an enum type. Consult the README for more information
+-}
+
+module TotalMap
+    ( TotalMap()
+    , generateAllConstructors
+    , allTags
+    , getTotalMap
+    , setTotalMap
+    , ixTotal
+    , IsEnumType
+    ) where
+
+import           Control.Lens         (FoldableWithIndex (..),
+                                       FunctorWithIndex (..), Lens',
+                                       TraversableWithIndex (..), itoList, lens)
+import           Data.Distributive    (Distributive (..))
+import           Data.Functor.Classes (Eq1 (..), Show1 (..))
+import           Data.Functor.Rep     (Representable (..))
+import           Data.List            (intercalate)
+import           Generics.SOP
+
+-- | Generate all constructors for some enum type.
+--
+-- TODO: This uses undefined internally as I can not convince the type checker that every constructor has no arguments. This shouldn't be an issue, but feels unsafe so probably should be changed
+generateAllConstructors :: IsEnumType tag => NP (K tag) (Code tag)
+generateAllConstructors = hliftA2 aux (hcpure (Proxy :: Proxy SListI) $ hpure undefined) injections
+  where
+    aux np (Fn inj) = K (to (SOP $ unK $ inj np))
+
+-- | A `TotalMap` is a total mapping from some enum type `tag` to some value `a`: it is isomorphic to `tag -> a`. It uses a generics-sop `NP` array to store all values, ensuring that every value of `tag` must have a corresponding value.
+data TotalMap (tag :: *) (a :: *) where
+    TotalMap :: (IsEnumType tag) => NP (K a) (Code tag) -> TotalMap tag a
+
+-- | A `TotalMap` where each value is its own key. This is the equivalent of `id`.
+allTags :: IsEnumType tag => TotalMap tag tag
+allTags = TotalMap generateAllConstructors
+
+--totalMapWithTag :: IsEnumType tag => TotalMap tag a -> TotalMap tag (tag, a)
+--totalMapWithTag = liftA2 (,) allTags
+
+instance Functor (TotalMap tag) where
+    fmap f (TotalMap np) = TotalMap $ hliftA (mapKK f) np
+
+instance IsEnumType tag => FunctorWithIndex tag (TotalMap tag) where
+    imap f tm = f <$> allTags <*> tm
+
+instance (IsEnumType tag) => Applicative (TotalMap tag) where
+    pure a = TotalMap $ hpure (K a)
+    TotalMap a <*> TotalMap b = TotalMap $ hliftA2 (mapKKK ($)) a b
+
+instance IsEnumType tag => Monad (TotalMap tag) where
+  tm >>= f = imap (\tag a -> getTotalMap (f a) tag) tm
+
+instance Foldable (TotalMap tag) where
+    foldMap f (TotalMap np) = foldMap f $ hcollapse np
+
+instance IsEnumType tag => FoldableWithIndex tag (TotalMap tag) where
+    ifoldMap f tm = foldMap (uncurry f) ((,) <$> allTags <*> tm)
+
+instance Traversable (TotalMap tag) where
+    sequenceA (TotalMap np) = TotalMap <$> hsequenceK np
+
+instance IsEnumType tag => TraversableWithIndex tag (TotalMap tag) where
+    itraverse func tm = traverse (uncurry func) ( (,) <$> allTags <*> tm)
+
+instance IsEnumType tag => Distributive (TotalMap tag) where
+  distribute = imap (\tag -> fmap (\tm -> getTotalMap tm tag)) . pure
+
+instance IsEnumType tag => Representable (TotalMap tag) where
+  type Rep (TotalMap tag) = tag
+  index = getTotalMap
+  tabulate func = TotalMap $ hmap (mapKK func) generateAllConstructors
+
+instance (IsEnumType tag) => Eq1 (TotalMap tag) where
+    liftEq f a b = foldr (&&) True (f <$> a <*> b)
+
+instance (IsEnumType tag, Eq a) => Eq (TotalMap tag a) where
+    (==) = liftEq (==)
+
+instance (IsEnumType tag, Show tag) => Show1 (TotalMap tag) where
+    liftShowsPrec f _ n tm ss =
+        "TotalMap [" ++
+        intercalate
+            ", "
+            (map (\(t, a) -> "(" ++ show t ++ "," ++ f n a "" ++ ")") $
+             itoList tm) ++
+        "]" ++ ss
+
+instance (IsEnumType tag, Show a, Show tag) => Show (TotalMap tag a) where
+    showsPrec n = liftShowsPrec showsPrec undefined n
+
+-- | Extract a value out of a `TotalMap`
+getTotalMap :: TotalMap tag a -> tag -> a
+getTotalMap (TotalMap tm) a = hcollapse (hapInjs tm !! (hindex $ from a))
+
+-- | Replace a value inside a `TotalMap`
+setTotalMap ::
+       forall tag a. IsEnumType tag
+    => TotalMap tag a
+    -> tag
+    -> a
+    -> TotalMap tag a
+setTotalMap (TotalMap tm) tag a =
+    let helper :: NP (K a) xss -> NS (NP f) xss -> NP (K a) xss
+        helper (k :* as) (S z) = k :* helper as z
+        helper (_ :* as) (Z _) = (K a) :* as
+        helper Nil _           = error "Unreachable"
+     in TotalMap (helper tm (unSOP $ from tag))
+
+-- | A `Lens` into a value of a `TotalMap`
+ixTotal :: IsEnumType tag => tag -> Lens' (TotalMap tag a) a
+ixTotal tag = lens (\tm -> getTotalMap tm tag) (\tm -> setTotalMap tm tag)
