diff --git a/config-ini.cabal b/config-ini.cabal
--- a/config-ini.cabal
+++ b/config-ini.cabal
@@ -1,7 +1,8 @@
 name:             config-ini
-version:          0.1.1.0
+version:          0.1.2.0
 synopsis:         A library for simple INI-based configuration files.
 homepage:         https://github.com/aisamanra/config-ini
+bug-reports:      https://github.com/aisamanra/config-ini/issues
 description:      The @config-ini@ library is a small monadic language
                   for writing simple configuration languages with convenient,
                   human-readable error messages.
@@ -20,7 +21,7 @@
 copyright:        ©2016 Getty Ritter
 category:         Configuration
 build-type:       Simple
-cabal-version:    >= 1.14
+cabal-version:    >= 1.10
 
 source-repository head
   type: git
@@ -38,7 +39,7 @@
   build-depends:       base                  >=4.7 && <4.10
                      , text                  >=1.2.2 && <1.3
                      , unordered-containers  >=0.2.7 && <0.3
-                     , transformers          >=0.5.2 && <0.6
+                     , transformers          >=0.4.1 && <0.6
                      , megaparsec            >=5.1.2 && <5.2
   default-language:    Haskell2010
 
@@ -88,3 +89,15 @@
                   , unordered-containers
                   , text
                   , directory
+
+test-suite test-doctest
+  if impl(ghc < 7.10)
+    buildable:      False
+  type:             exitcode-stdio-1.0
+  ghc-options:      -Wall
+  default-language: Haskell2010
+  hs-source-dirs:   test/doctest
+  main-is:          Main.hs
+  build-depends:    base
+                  , doctest
+                  , microlens
diff --git a/examples/config-example/Main.hs b/examples/config-example/Main.hs
--- a/examples/config-example/Main.hs
+++ b/examples/config-example/Main.hs
@@ -25,7 +25,7 @@
     port <- fieldOf "port" number
     return NetworkConfig { netHost = host, netPort = port }
   locCf <- sectionMb "LOCAL" $
-    LocalConfig <$> field "user"
+    LocalConfig `fmap` field "user"
   return Config { cfNetwork = netCf, cfLocal = locCf }
 
 main :: IO ()
diff --git a/src/Data/Ini/Config.hs b/src/Data/Ini/Config.hs
--- a/src/Data/Ini/Config.hs
+++ b/src/Data/Ini/Config.hs
@@ -30,7 +30,7 @@
 , flag
 ) where
 
-import           Control.Applicative (Alternative(..))
+import           Control.Applicative (Applicative(..), Alternative(..))
 import           Control.Monad.Trans.Except
 import qualified Data.HashMap.Strict as HM
 import           Data.Ini.Config.Raw
@@ -137,7 +137,7 @@
 --   >>> parseIniFile "[MAIN]\nx = hello\n" $ section "MAIN" (field "x")
 --   Right "hello"
 --   >>> parseIniFile "[MAIN]\nx = hello\n" $ section "MAIN" (field "y")
---   Left "Missing field \"y\" in section \"main\""
+--   Left "Missing field \"y\" in section \"MAIN\""
 field :: Text -> SectionParser Text
 field name = SectionParser $ vValue `fmap` rawField name
 
@@ -173,7 +173,7 @@
 --   fail.
 --
 --   >>> parseIniFile "[MAIN]\nx = 72\n" $ section "MAIN" (fieldMbOf "x" number)
---   Right 72
+--   Right (Just 72)
 --   >>> parseIniFile "[MAIN]\nx = hello\n" $ section "MAIN" (fieldMbOf "x" number)
 --   Left "Line 2, in section \"MAIN\": Unable to parse \"hello\" as a value of type Integer"
 --   >>> parseIniFile "[MAIN]\nx = 72\n" $ section "MAIN" (fieldMbOf "y" number)
@@ -226,7 +226,7 @@
 --   >>> parseIniFile "[MAIN]\nx = yes\n" $ section "MAIN" (fieldFlag "x")
 --   Right True
 --   >>> parseIniFile "[MAIN]\nx = yes\n" $ section "MAIN" (fieldFlag "y")
---   Left "Missing field \"y\" in section \"main\""
+--   Left "Missing field \"y\" in section \"MAIN\""
 fieldFlag :: Text -> SectionParser Bool
 fieldFlag name = fieldOf name flag
 
@@ -248,7 +248,7 @@
 --   with a human-readable error message if reading fails.
 --
 --   >>> readable "(5, 7)" :: Either String (Int, Int)
---   Right (5, 7)
+--   Right (5,7)
 --   >>> readable "hello" :: Either String (Int, Int)
 --   Left "Unable to parse \"hello\" as a value of type (Int,Int)"
 readable :: forall a. (Read a, Typeable a) => Text -> Either String a
@@ -294,7 +294,7 @@
 --   >>> flag "F"
 --   Right False
 --   >>> flag "That's a secret!"
---   Left "Unable to parse \"that's a secret!\" as a boolean"
+--   Left "Unable to parse \"That's a secret!\" as a boolean"
 flag :: Text -> Either String Bool
 flag s = case T.toLower s of
   "true"  -> Right True
@@ -307,6 +307,41 @@
   "n"     -> Right False
   _       -> Left ("Unable to parse " ++ show s ++ " as a boolean")
 
+
+-- $setup
+--
+-- >>> :{
+-- data NetworkConfig = NetworkConfig
+--    { netHost :: String, netPort :: Int }
+--     deriving (Eq, Show)
+-- >>> :}
+--
+-- >>> :{
+-- data LocalConfig = LocalConfig
+--   { localUser :: Text }
+--     deriving (Eq, Show)
+-- >>> :}
+--
+-- >>> :{
+-- data Config = Config
+--   { cfNetwork :: NetworkConfig, cfLocal :: Maybe LocalConfig }
+--     deriving (Eq, Show)
+-- >>> :}
+--
+-- >>> :{
+-- let configParser = do
+--       netCf <- section "NETWORK" $ do
+--         host <- fieldOf "host" string
+--         port <- fieldOf "port" number
+--         return NetworkConfig { netHost = host, netPort = port }
+--       locCf <- sectionMb "LOCAL" $
+--         LocalConfig <$> field "user"
+--       return Config { cfNetwork = netCf, cfLocal = locCf }
+-- >>> :}
+--
+-- >>> :{
+--    let example = "[NETWORK]\nhost = example.com\nport = 7878\n\n# here is a comment\n[LOCAL]\nuser = terry\n"
+-- >>> :}
 
 -- $main
 -- The 'config-ini' library exports some simple monadic functions to
diff --git a/src/Data/Ini/Config/Raw.hs b/src/Data/Ini/Config/Raw.hs
--- a/src/Data/Ini/Config/Raw.hs
+++ b/src/Data/Ini/Config/Raw.hs
@@ -43,10 +43,13 @@
   Right v  -> Right v
 
 pIni :: Parser Ini
-pIni = sBlanks *> (go `fmap` (many (pSection <?> "section") <* eof))
-  where go vs = Ini $ HM.fromList [ (T.toLower (isName v), v)
-                                  | v <- vs
-                                  ]
+pIni = do
+  sBlanks
+  vs <- many (pSection <?> "section")
+  void eof
+  return $ Ini $ HM.fromList [ (T.toLower (isName v), v)
+                             | v <- vs
+                             ]
 
 sBlanks :: Parser ()
 sBlanks = skipMany (void eol <|> sComment)
diff --git a/test/doctest/Main.hs b/test/doctest/Main.hs
new file mode 100644
--- /dev/null
+++ b/test/doctest/Main.hs
@@ -0,0 +1,8 @@
+module Main where
+
+import Test.DocTest (doctest)
+
+main :: IO ()
+main = do
+  doctest [ "src/Data/Ini/Config.hs", "-XOverloadedStrings"  ]
+  doctest [ "src/Data/Ini/Config/Lens.hs", "-XRankNTypes", "-XOverloadedStrings" ]
diff --git a/test/ini-compat/Main.hs b/test/ini-compat/Main.hs
--- a/test/ini-compat/Main.hs
+++ b/test/ini-compat/Main.hs
@@ -10,8 +10,8 @@
 
 import           Test.QuickCheck
 
-iniEquiv :: I1.Ini -> Bool
-iniEquiv raw = case (i1, i2) of
+iniEquiv :: ArbIni -> Bool
+iniEquiv (ArbIni raw) = case (i1, i2) of
    (Right i1', Right i2') ->
      let i1'' = lower i1'
          i2'' = toMaps i2'
@@ -28,14 +28,22 @@
 toMaps :: I2.Ini -> HashMap Text (HashMap Text Text)
 toMaps (I2.Ini m) = fmap (fmap I2.vValue . I2.isVals) m
 
-instance Arbitrary I1.Ini where
-  arbitrary = (I1.Ini . HM.fromList) <$> listOf sections
-    where sections = (,) <$> str <*> section
-          str = (T.pack <$> arbitrary) `suchThat` (\ t ->
+newtype ArbIni = ArbIni I1.Ini deriving (Show)
+
+instance Arbitrary ArbIni where
+  arbitrary = (ArbIni . I1.Ini . HM.fromList) `fmap` listOf sections
+    where sections = do
+            name <- str
+            sec  <- section
+            return (name, sec)
+          str = (T.pack `fmap` arbitrary) `suchThat` (\ t ->
                    T.all (\ c -> isAlphaNum c || c == ' ')
                    t && not (T.null t))
-          section = HM.fromList <$> listOf kv
-          kv = (,) <$> str <*> str
+          section = HM.fromList `fmap` listOf kv
+          kv = do
+            name <- str
+            val  <- str
+            return (name, val)
 
 main :: IO ()
 main = quickCheck iniEquiv
