diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,7 @@
+## 0.2.0
+
+* Make `PathMultiPiece` instance for lists based on `PathPiece` [Yesod issue #932](https://github.com/yesodweb/yesod/issues/932)
+
+## 0.1.5
+
+Added more integral instances, and check bounds on them [#5](https://github.com/yesodweb/path-pieces/pull/5).
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,6 @@
+## path-pieces
+
+Defines two typeclasses used for converting Haskell data types to and from route pieces.
+Used in Yesod to automatically marshall data in the request path.
+
+see http://www.yesodweb.com/ for more information.
diff --git a/Web/PathPieces.hs b/Web/PathPieces.hs
--- a/Web/PathPieces.hs
+++ b/Web/PathPieces.hs
@@ -1,55 +1,167 @@
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE TypeSynonymInstances #-}
+{-# LANGUAGE FlexibleInstances, TypeSynonymInstances, OverloadedStrings #-}
 module Web.PathPieces
-    ( SinglePiece (..)
-    , MultiPiece (..)
+    ( PathPiece (..)
+    , PathMultiPiece (..)
+    , readFromPathPiece
+    , showToPathPiece
+    -- * Deprecated
+    , toSinglePiece
+    , toMultiPiece
+    , fromSinglePiece
+    , fromMultiPiece
     ) where
 
-import Data.Int (Int64)
+import Data.Int (Int8, Int16, Int32, Int64)
+import Data.Word (Word, Word8, Word16, Word32, Word64)
 import qualified Data.Text as S
 import qualified Data.Text.Lazy as L
 import qualified Data.Text.Read
+import Data.Time (Day)
+import Control.Exception (assert)
+import Text.Read (readMaybe)
 
-class SinglePiece s where
-    fromSinglePiece :: S.Text -> Maybe s
-    toSinglePiece :: s -> S.Text
-instance SinglePiece String where
-    fromSinglePiece s = if S.null s then Nothing else Just (S.unpack s)
-    toSinglePiece = S.pack
-instance SinglePiece S.Text where
-    fromSinglePiece s = if S.null s then Nothing else Just s
-    toSinglePiece = id
-instance SinglePiece L.Text where
-    fromSinglePiece s = if S.null s then Nothing else Just (L.fromChunks [s])
-    toSinglePiece = S.concat . L.toChunks
-instance SinglePiece Integer where
-    fromSinglePiece s =
-        case Data.Text.Read.decimal s of
-            Right (i, _) -> Just i
-            Left _ -> Nothing
-    toSinglePiece = S.pack . show
-instance SinglePiece Int where
-    fromSinglePiece s =
-        case Data.Text.Read.decimal s of
-            Right (i, _) -> Just i
-            Left _ -> Nothing
-    toSinglePiece = S.pack . show
-instance SinglePiece Int64 where
-    fromSinglePiece s =
-        case Data.Text.Read.decimal s of
-            Right (i, _) -> Just i
-            Left _ -> Nothing
-    toSinglePiece = S.pack . show
+class PathPiece s where
+    fromPathPiece :: S.Text -> Maybe s
+    toPathPiece :: s -> S.Text
 
-class MultiPiece s where
-    fromMultiPiece :: [S.Text] -> Maybe s
-    toMultiPiece :: s -> [S.Text]
-instance MultiPiece [String] where
-    fromMultiPiece = Just . map S.unpack
-    toMultiPiece = map S.pack
-instance MultiPiece [S.Text] where
-    fromMultiPiece = Just
-    toMultiPiece = id
-instance MultiPiece [L.Text] where
-    fromMultiPiece = Just . map (L.fromChunks . return)
-    toMultiPiece = map $ S.concat . L.toChunks
+instance PathPiece () where
+    fromPathPiece t = if t == "_" then Just () else Nothing
+    toPathPiece () = "_"
+
+instance PathPiece String where
+    fromPathPiece = Just . S.unpack
+    toPathPiece = S.pack
+
+instance PathPiece S.Text where
+    fromPathPiece = Just
+    toPathPiece = id
+
+instance PathPiece L.Text where
+    fromPathPiece = Just . L.fromChunks . return
+    toPathPiece = S.concat . L.toChunks
+
+parseIntegral :: (Integral a, Bounded a, Ord a) => S.Text -> Maybe a
+parseIntegral s = n
+    where
+    n = case Data.Text.Read.signed Data.Text.Read.decimal s of
+        Right (i, "") | i <= top && i >= bot -> Just (fromInteger i)
+        _ -> Nothing
+    Just witness = n
+    top = toInteger (maxBound `asTypeOf` witness)
+    bot = toInteger (minBound `asTypeOf` witness)
+
+instance PathPiece Integer where
+    fromPathPiece s =
+        case Data.Text.Read.signed Data.Text.Read.decimal s of
+            Right (i, "") -> Just i
+            _ -> Nothing
+    toPathPiece = S.pack . show
+
+instance PathPiece Int where
+    fromPathPiece = parseIntegral
+    toPathPiece = S.pack . show
+
+instance PathPiece Int8 where
+    fromPathPiece = parseIntegral
+    toPathPiece = S.pack . show
+
+instance PathPiece Int16 where
+    fromPathPiece = parseIntegral
+    toPathPiece = S.pack . show
+
+instance PathPiece Int32 where
+    fromPathPiece = parseIntegral
+    toPathPiece = S.pack . show
+
+instance PathPiece Int64 where
+    fromPathPiece = parseIntegral
+    toPathPiece = S.pack . show
+
+instance PathPiece Word where
+    fromPathPiece = parseIntegral
+    toPathPiece = S.pack . show
+
+instance PathPiece Word8 where
+    fromPathPiece = parseIntegral
+    toPathPiece = S.pack . show
+
+instance PathPiece Word16 where
+    fromPathPiece = parseIntegral
+    toPathPiece = S.pack . show
+
+instance PathPiece Word32 where
+    fromPathPiece = parseIntegral
+    toPathPiece = S.pack . show
+
+instance PathPiece Word64 where
+    fromPathPiece = parseIntegral
+    toPathPiece = S.pack . show
+
+instance PathPiece Bool where
+    fromPathPiece t =
+        case filter (null . snd) $ reads $ S.unpack t of
+            (a, s):_ -> assert (null s) (Just a)
+            _        -> Nothing
+    toPathPiece = S.pack . show
+
+instance PathPiece Day where
+    fromPathPiece t =
+        case reads $ S.unpack t of
+            [(a,"")] -> Just a
+            _ -> Nothing
+    toPathPiece = S.pack . show
+
+instance (PathPiece a) => PathPiece (Maybe a) where
+    fromPathPiece s = case S.stripPrefix "Just " s of
+        Just r -> Just `fmap` fromPathPiece r
+        _ -> case s of
+            "Nothing" -> Just Nothing
+            _ -> Nothing
+    toPathPiece m = case m of
+        Just s -> "Just " `S.append` toPathPiece s
+        _ -> "Nothing"
+
+class PathMultiPiece s where
+    fromPathMultiPiece :: [S.Text] -> Maybe s
+    toPathMultiPiece :: s -> [S.Text]
+
+instance PathPiece a => PathMultiPiece [a] where
+    fromPathMultiPiece = mapM fromPathPiece
+    toPathMultiPiece = map toPathPiece
+
+-- | A function for helping generate free 'PathPiece'
+--   instances for enumeration data types 
+--   that have derived 'Read' and 'Show' instances.
+--   Intended to be used like this:
+--
+--   > data MyData = Foo | Bar | Baz
+--   >   deriving (Read,Show)
+--   > instance PathPiece MyData where
+--   >   fromPathPiece = readFromPathPiece
+--   >   toPathPiece = showToPathPiece
+--
+--  Since 0.2.1. 
+readFromPathPiece :: Read s => S.Text -> Maybe s
+readFromPathPiece = readMaybe . S.unpack
+
+-- | See the documentation for 'readFromPathPiece'.
+--
+--  Since 0.2.1. 
+showToPathPiece :: Show s => s -> S.Text
+showToPathPiece = S.pack . show
+
+{-# DEPRECATED toSinglePiece "Use toPathPiece instead of toSinglePiece" #-}
+toSinglePiece :: PathPiece p => p -> S.Text
+toSinglePiece = toPathPiece
+
+{-# DEPRECATED fromSinglePiece "Use fromPathPiece instead of fromSinglePiece" #-}
+fromSinglePiece :: PathPiece p => S.Text -> Maybe p
+fromSinglePiece = fromPathPiece
+
+{-# DEPRECATED toMultiPiece "Use toPathMultiPiece instead of toMultiPiece" #-}
+toMultiPiece :: PathMultiPiece ps => ps -> [S.Text]
+toMultiPiece = toPathMultiPiece
+
+{-# DEPRECATED fromMultiPiece "Use fromPathMultiPiece instead of fromMultiPiece" #-}
+fromMultiPiece :: PathMultiPiece ps => [S.Text] -> Maybe ps
+fromMultiPiece = fromPathMultiPiece
diff --git a/path-pieces.cabal b/path-pieces.cabal
--- a/path-pieces.cabal
+++ b/path-pieces.cabal
@@ -1,22 +1,39 @@
 name:            path-pieces
-version:         0.0.0
+version:         0.2.1
 license:         BSD3
 license-file:    LICENSE
 author:          Michael Snoyman <michael@snoyman.com>
 maintainer:      Michael Snoyman <michael@snoyman.com>
 synopsis:        Components of paths.
+description:    Hackage documentation generation is not reliable. For up to date documentation, please see: <http://www.stackage.org/package/path-pieces>.
 category:        Web, Yesod
 stability:       unstable
-cabal-version:   >= 1.6
+cabal-version:   >= 1.8
 build-type:      Simple
-homepage:        http://github.com/snoyberg/path-pieces
+extra-source-files:
+  test/main.hs
+  ChangeLog.md
+  README.md
 
 library
     build-depends:   base             >= 4       && < 5
-                   , text             >= 0.5     && < 0.12
+                   , text             >= 0.5
+                   , time
     exposed-modules: Web.PathPieces
     ghc-options:     -Wall
 
+test-suite test
+    type:          exitcode-stdio-1.0
+    main-is:       main.hs
+    hs-source-dirs: test
+    ghc-options:   -Wall
+    build-depends:   HUnit
+                   , hspec >= 1.3
+                   , base >= 4 && < 5
+                   , QuickCheck
+                   , path-pieces
+                   , text
+
 source-repository head
   type:     git
-  location: git://github.com/snoyberg/path-pieces.git
+  location: https://github.com/yesodweb/path-pieces
diff --git a/test/main.hs b/test/main.hs
new file mode 100644
--- /dev/null
+++ b/test/main.hs
@@ -0,0 +1,82 @@
+{-# Language ScopedTypeVariables #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module Main where
+
+import Test.Hspec
+import Test.Hspec.QuickCheck(prop)
+import Test.QuickCheck
+
+import Web.PathPieces
+import qualified Data.Text as T
+import Data.Maybe (fromJust)
+
+-- import FileLocation (debug)
+
+instance Arbitrary T.Text where
+  arbitrary = fmap T.pack arbitrary
+
+
+main :: IO ()
+main = hspec spec
+
+spec :: Spec
+spec = do
+  describe "PathPiece" $ do
+    prop "toPathPiece <=> fromPathPiece String" $ \(p::String) ->
+      case (fromPathPiece . toPathPiece) p of
+        Nothing -> null p
+        Just pConverted -> p == pConverted
+
+    prop "toPathPiece <=> fromPathPiece Text" $ \(p::T.Text) ->
+      case (fromPathPiece . toPathPiece) p of
+        Nothing -> T.null p
+        Just pConverted -> p == pConverted
+
+    prop "toPathPiece <=> fromPathPiece Int" $ \(p::Int) ->
+      case (fromPathPiece . toPathPiece) p of
+        Nothing -> False
+        Just pConverted -> p == pConverted
+
+    prop "toPathPiece <=> fromPathPiece Bool" $ \(p::Bool) ->
+      case (fromPathPiece . toPathPiece) p of
+        Nothing -> False
+        Just pConverted -> p == pConverted
+
+    prop "toPathPiece <=> fromPathPiece Maybe String" $ \(p::Maybe String) ->
+      case (fromPathPiece . toPathPiece) p of
+        Nothing -> False
+        Just pConverted -> p == pConverted
+
+  describe "PathMultiPiece" $ do
+    prop "toPathMultiPiece <=> fromPathMultiPiece String" $ \(p::[String]) ->
+      p == (fromJust . fromPathMultiPiece . toPathMultiPiece) p
+
+    prop "toPathMultiPiece <=> fromPathMultiPiece Text" $ \(p::[T.Text]) ->
+      p == (fromJust . fromPathMultiPiece . toPathMultiPiece) p
+
+
+  describe "SinglePiece" $ do
+    prop "toPathPiece <=> fromPathPiece String" $ \(p::String) ->
+      case (fromPathPiece . toPathPiece) p of
+        Nothing -> null p
+        Just pConverted -> p == pConverted
+
+    prop "toPathPiece <=> fromPathPiece Text" $ \(p::T.Text) ->
+      case (fromPathPiece . toPathPiece) p of
+        Nothing -> T.null p
+        Just pConverted -> p == pConverted
+
+    prop "toPathPiece <=> fromPathPiece Int" $ \(p::Int) ->
+      case (fromPathPiece . toPathPiece) p of
+        Nothing -> p < 0
+        Just pConverted -> p == pConverted
+
+  describe "MultiPiece" $ do
+    prop "toPathMultiPiece <=> fromPathMultiPiece String" $ \(p::[String]) ->
+      p == (fromJust . fromPathMultiPiece . toPathMultiPiece) p
+
+    prop "toPathMultiPiece <=> fromPathMultiPiece Text" $ \(p::[T.Text]) ->
+      p == (fromJust . fromPathMultiPiece . toPathMultiPiece) p
+
+  it "bad ints are rejected" $ fromPathPiece (T.pack "123hello")
+    `shouldBe` (Nothing :: Maybe Int)
