diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown
--- a/CHANGELOG.markdown
+++ b/CHANGELOG.markdown
@@ -1,3 +1,9 @@
+0.3.3
+=====
+
+  * Removed the unnecessary `AsEmpty` and `AsUnset` constraints on the error type
+    in the `flag` and `switch` parsers.
+
 0.3.2
 =====
 
diff --git a/envparse.cabal b/envparse.cabal
--- a/envparse.cabal
+++ b/envparse.cabal
@@ -1,5 +1,5 @@
 name:                envparse
-version:             0.3.2
+version:             0.3.3
 synopsis:            Parse environment variables
 description:
   Here's a simple example of a program that uses @envparse@'s parser:
@@ -59,7 +59,8 @@
   CHANGELOG.markdown
   example/Main.hs
   example/CustomError.hs
-  example/Generic.hs
+  example/Generic0.hs
+  example/Generic1.hs
 
 source-repository head
   type:     git
@@ -68,7 +69,7 @@
 source-repository this
   type:     git
   location: https://github.com/supki/envparse
-  tag:      0.3.2
+  tag:      0.3.3
 
 library
   default-language:
diff --git a/example/Generic.hs b/example/Generic.hs
deleted file mode 100644
--- a/example/Generic.hs
+++ /dev/null
@@ -1,46 +0,0 @@
-{-# LANGUAGE CPP #-}
-#if __GLASGOW_HASKELL__ < 710
-module Main (main) where
-
-main :: IO ()
-main =
-  return ()
-#else
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE DeriveAnyClass #-}
-{-# LANGUAGE DeriveGeneric #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE NamedFieldPuns #-}
-{-# LANGUAGE TypeOperators #-}
--- | Greetings for $NAME
---
--- @
--- % GENERIC_NAME=a5579150 runhaskell -isrc example/Generic.hs
--- Hello, a5579150!
--- % GENERIC_NAME=a5579150 GENERIC_QUIET=1 runhaskell -isrc example/Generic.hs
--- %
--- @
-module Main (main) where
-
-import Control.Monad (unless)
-import Env
-import Env.Generic
-
-
-data Hello = Hello
-  { name  :: String ? "Target for the greeting"
-  , quiet :: Bool   ? "Whether to actually print the greeting"
-  } deriving (Show, Eq, Generic)
-
-instance Record Error Hello
-
-main :: IO ()
-main = do
-  Hello {name=Help n, quiet=Help q} <- hello
-  unless q $
-    putStrLn ("Hello, " ++ n ++ "!")
-
-hello :: IO Hello
-hello =
-  Env.parse (header "envparse example") (prefixed "GENERIC_" record)
-#endif
diff --git a/example/Generic0.hs b/example/Generic0.hs
new file mode 100644
--- /dev/null
+++ b/example/Generic0.hs
@@ -0,0 +1,30 @@
+{-# LANGUAGE CPP #-}
+#if __GLASGOW_HASKELL__ < 710
+module Main (main) where
+
+main :: IO ()
+main =
+  return ()
+#else
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+module Main (main) where
+
+import Env
+import Env.Generic
+
+
+data Hello = Hello
+  { name  :: String
+  , count :: Int
+  , quiet :: Bool
+  } deriving (Show, Eq, Generic)
+
+instance Record Error Hello
+
+main :: IO ()
+main = do
+  hello <- Env.parse (header "envparse example") record
+  print (hello :: Hello)
+#endif
diff --git a/example/Generic1.hs b/example/Generic1.hs
new file mode 100644
--- /dev/null
+++ b/example/Generic1.hs
@@ -0,0 +1,31 @@
+{-# LANGUAGE CPP #-}
+#if __GLASGOW_HASKELL__ < 710
+module Main (main) where
+
+main :: IO ()
+main =
+  return ()
+#else
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TypeOperators #-}
+module Main (main) where
+
+import Env
+import Env.Generic
+
+
+data Hello = Hello
+  { name  :: String ? "Whom shoud I greet?"
+  , count :: Int    ? "How many times to greet them?"
+  , quiet :: Bool   ? "Should I be quiet instead?"
+  } deriving (Show, Eq, Generic)
+
+instance Record Error Hello
+
+main :: IO ()
+main = do
+  hello <- Env.parse (header "envparse example") record
+  print (hello :: Hello)
+#endif
diff --git a/src/Env/Generic.hs b/src/Env/Generic.hs
--- a/src/Env/Generic.hs
+++ b/src/Env/Generic.hs
@@ -9,6 +9,85 @@
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE TypeOperators #-}
+-- | Using the 'G.Generic' facility, this module can derive 'Env.Parser's automatically.
+--
+-- If you have a simple record:
+--
+-- @
+-- {-\# LANGUAGE DeriveGeneric #-}
+-- {-\# LANGUAGE MultiParamTypeClasses #-}
+--
+-- import Env
+-- import Env.Generic
+--
+-- data Hello = Hello
+--   { name  :: String
+--   , count :: Int
+--   , quiet :: Bool
+--   } deriving (Show, Eq, Generic)
+--
+-- instance Record Error Hello
+--
+-- main :: IO ()
+-- main = do
+--   hello <- Env.parse (header "envparse example") 'record'
+--   print (hello :: Hello)
+-- @
+--
+-- The generic implementation of the 'record' method translates named fields to field parsers:
+--
+-- @
+-- % NAME=bob COUNT=3 runhaskell -isrc example/Generic0.hs
+-- Hello {name = "bob", count = 3, quiet = False}
+-- @
+--
+-- If you want to adorn the ugly default help message, augment the fields with descriptions:
+--
+-- @
+-- {-\# LANGUAGE DataKinds #-}
+-- {-\# LANGUAGE DeriveGeneric #-}
+-- {-\# LANGUAGE MultiParamTypeClasses #-}
+-- {-\# LANGUAGE TypeOperators #-}
+--
+-- import Env
+-- import Env.Generic
+--
+-- data Hello = Hello
+--   { name  :: String ? __"Whom shoud I greet?"__
+--   , count :: Int    ? __"How many times to greet them?"__
+--   , quiet :: Bool   ? __"Should I be quiet instead?"__
+--   } deriving (Show, Eq, Generic)
+--
+-- instance Record Error Hello
+--
+-- main :: IO ()
+-- main = do
+--   hello <- Env.parse (header "envparse example") record
+--   print (hello :: Hello)
+-- @
+--
+-- @
+-- % runhaskell -isrc example/Generic1.hs
+-- envparse example
+--
+-- Available environment variables:
+--
+--   COUNT                  __How many times to greet them?__
+--   NAME                   __Whom shoud I greet?__
+--   QUIET                  __Should I be quiet instead?__
+--
+-- Parsing errors:
+--
+--   COUNT is unset
+--   NAME is unset
+-- @
+--
+-- Note that this has an effect of wrapping the values in the 'Help' constructor:
+--
+-- @
+-- % NAME=bob COUNT=3 QUIET='YES' runhaskell -isrc example/Generic1.hs
+-- Hello {name = Help {unHelp = "bob"}, count = Help {unHelp = 3}, quiet = Help {unHelp = True}}
+-- @
 module Env.Generic
   ( Record(..)
   , Field(..)
@@ -32,33 +111,38 @@
 import qualified Env
 
 
+-- | Given a @Record e a@ instance, a value of the type @a@ can be parsed from the environment.
+-- If the parsing fails, a value of an error type @e@ is returned.
+--
+-- The 'record' method has a default implementation for any type that has a 'G.Generic' instance. If you
+-- need to choose a concrete type for @e@, the default error type 'Env.Error' is a good candidate. Otherwise,
+-- the features you'll use in your parsers will naturally guide GHC to compute the set of required
+-- constraints on @e@.
 class Record e a where
   record :: Env.Parser e a
   default record :: (r ~ G.Rep a, G.Generic a, GRecord e r) => Env.Parser e a
   record =
     fmap G.to (gr State {statePrefix="", stateCon="", stateVar=""})
 
--- | Generic parsing state.
 data State = State
-  { statePrefix :: String -- ^ All variables' names have this prefix.
-  , stateCon    :: String -- ^ Constructor currently being processed.
-  , stateVar    :: String -- ^ Variable name to use for the next component.
+  { statePrefix :: String -- All the variables' names have this prefix.
+  , stateCon    :: String -- The constructor currently being processed.
+  , stateVar    :: String -- The variable name to use for the next component.
   } deriving (Show, Eq)
 
 class GRecord e f where
   gr :: State -> Env.Parser e (f a)
 
--- | We are not interested in any metadata of the type constructor definition.
 instance GRecord e a => GRecord e (G.D1 c a) where
   gr =
     fmap G.M1 . gr
 
--- | Constant values are converted to 'Env.Parser's using their 'Field' instance.
+-- Constant values are converted to 'Env.Parser's using their 'Field' instance.
 instance (Env.AsUnset e, Field e a) => GRecord e (G.K1 i a) where
   gr State {stateVar} =
     fmap G.K1 (field stateVar Nothing)
 
--- | Constructor's name is used as a prefix to try to remove from
+-- Constructor's name is used as a prefix to try to remove from
 -- selectors when building environment variable names.
 instance (G.Constructor c, GRecord e a) => GRecord e (G.C1 c a) where
   gr state =
@@ -66,17 +150,14 @@
    where
     con = G.conName (G.M1 Proxy :: G.M1 t c Proxy b)
 
--- | Products are converted to products of parsers.
 instance (GRecord e f, GRecord e g) => GRecord e (f G.:*: g) where
   gr x =
     liftA2 (G.:*:) (gr x) (gr x)
 
--- | Sums are converted to sums of parsers.
 instance (GRecord e f, GRecord e g) => GRecord e (f G.:+: g) where
   gr x =
     fmap G.L1 (gr x) <|> fmap G.R1 (gr x)
 
--- | Record selectors' names determine suffixes of environment variables' names.
 instance (G.Selector c, Type c ~ 'Record, GRecord e a) => GRecord e (G.S1 c a) where
   gr state@State {statePrefix, stateCon} =
     fmap G.M1 (gr state {stateVar=statePrefix ++ suffix})
@@ -88,7 +169,6 @@
         y <- List.stripPrefix (map Char.toLower stateCon) sel
         camelTo2 y <$ guard (not (List.null y))
 
--- | Stolen from Aeson and adapted.
 camelTo2 :: String -> String
 camelTo2 = map Char.toUpper . go2 . go1
  where
@@ -100,14 +180,21 @@
   go2 (l:u:xs) | Char.isLower l && Char.isUpper u = l : '_' : u : go2 xs
   go2 (x:xs) = x : go2 xs
 
--- | Decide whether the constructor is a record.
 type family Type x :: ConType where
   Type G.NoSelector = 'Plain
   Type x = 'Record
 
--- | Constructor can be either a plain thing or a record.
 data ConType = Plain | Record
 
+-- | Given a @Field e a@ instance, a value of the type @a@ can be parsed from an environment variable.
+-- If the parsing fails, a value of an error type @e@ is returned.
+--
+-- The 'field' method has a default implementation for any type that has a 'Read' instance. If you
+-- need to choose a concrete type for @e@, the default error type 'Env.Error' is a good candidate. Otherwise,
+-- the features you'll use in your parsers will naturally guide GHC to compute the set of required
+-- constraints on @e@.
+--
+-- The annotated instances do not use the default implementation.
 class Field e a where
   field :: String -> Maybe String -> Env.Parser e a
   default field :: (Env.AsUnset e, Env.AsUnread e, Read a) => String -> Maybe String -> Env.Parser e a
@@ -142,10 +229,12 @@
 
 instance (Env.AsUnset e, Env.AsUnread e) => Field e Double
 
+-- | Uses the 'String' value verbatim.
 instance Env.AsUnset e => Field e String where
   field name help =
     Env.var Env.str name (foldMap Env.help help)
 
+-- | Expects a single-character 'String' value.
 instance (Env.AsUnset e, Env.AsUnread e) => Field e Char where
   field name help =
     Env.var reader name (foldMap Env.help help)
@@ -154,14 +243,22 @@
       [c] -> pure c
       str -> Left (Env.unread str)
 
-instance (Env.AsUnset e, Env.AsEmpty e) => Field e Bool where
+-- | Any set and non-empty value parses to a 'True'; otherwise, it's a 'False'. This parser
+-- never fails.
+instance Field e Bool where
   field name help =
     Env.switch name (foldMap Env.help help)
 
--- | Variable tagged with its help message.
+-- | A field annotation.
+--
+-- If you annotate a record field with a 'Symbol' literal (that is, a statically known type level string)
+-- the derivation machinery will use the literal in the help message.
+--
+-- Please remember that the values of the annotated fields are wrapped in the 'Help' constructor.
 newtype a ? tag = Help { unHelp :: a }
     deriving (Show, Eq, Functor, Foldable, Traversable)
 
+-- | Augments the underlying field parser with the help message.
 instance (G.KnownSymbol tag, Field e a) => Field e (a ? tag) where
   field name _ =
     fmap Help (field name (pure (G.symbolVal (Proxy :: Proxy tag))))
diff --git a/src/Env/Parse.hs b/src/Env/Parse.hs
--- a/src/Env/Parse.hs
+++ b/src/Env/Parse.hs
@@ -107,13 +107,15 @@
 --
 -- /Note:/ this parser never fails.
 flag
-  :: forall e a. (Error.AsUnset e, Error.AsEmpty e)
-  => a -- ^ default value
+  :: a -- ^ default value
   -> a -- ^ active value
   -> String -> Mod Flag a -> Parser e a
 flag f t n (Mod g) = Parser . liftAlt $ VarF
   { varfName    = n
-  , varfReader  = \name -> Right . either (const f) (const t) . (nonempty :: Reader e String) <=< lookupVar name
+  , varfReader  = \name env ->
+      pure $ case (nonempty :: Reader Error.Error String) =<< lookupVar name env of
+        Left  _ -> f
+        Right _ -> t
   , varfHelp    = flagHelp
   , varfDef     = Just f
   , varfHelpDef = Nothing
@@ -123,8 +125,8 @@
 
 -- | A simple boolean 'flag'
 --
--- /Note:/ the same caveats apply.
-switch :: (Error.AsUnset e, Error.AsEmpty e) => String -> Mod Flag Bool -> Parser e Bool
+-- /Note:/ this parser never fails.
+switch :: String -> Mod Flag Bool -> Parser e Bool
 switch = flag False True
 
 -- | The trivial reader
