diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.markdown
@@ -0,0 +1,13 @@
+0.2.0
+=====
+
+  * Added `prefixed`.
+
+  * Added `parseOr`, a slightly generalized version of `parse`.
+
+  * Renamed `parseTest` to `parsePure`
+
+0.1.0
+=====
+
+  * Initial release.
diff --git a/envparse.cabal b/envparse.cabal
--- a/envparse.cabal
+++ b/envparse.cabal
@@ -1,8 +1,8 @@
 name:                envparse
-version:             0.1.0
+version:             0.2.0
 synopsis:            Parse environment variables
 description:
-  Here's a simple example
+  Here's a simple example of a program that uses @envparse@'s parser:
   .
   @
   module Main (main) where
@@ -23,7 +23,28 @@
   &#x20; unless quiet $
   &#x20;   putStrLn (\"Hello, \" ++ name ++ \"!\")
   @
-homepage:            http://example.com/
+  .
+  The @NAME@ environment variable is mandatory and contains the name of the person to
+  greet. @QUIET@, on the other hand, is an optional boolean flag, false by default, that
+  decides whether the greeting should be silent.
+  .
+  If the @NAME@ variable is undefined in the environment then running the program will
+  result in the following help text:
+  .
+  @
+  envparse example
+  &#x20;
+  Available environment variables:
+  &#x20;
+  &#x20; NAME                   Target for the greeting
+  &#x20; QUIET                  Whether to actually print the
+  &#x20;                        greeting
+  &#x20;
+  Parsing errors:
+  &#x20;
+  &#x20; NAME is missing
+  @
+homepage:            https://supki.github.io/envparse
 license:             BSD2
 license-file:        LICENSE
 author:              Matvey Aksenov
@@ -34,11 +55,17 @@
 cabal-version:       >= 1.10
 extra-source-files:
   README.markdown
+  CHANGELOG.markdown
   example/Main.hs
 
 source-repository head
   type:     git
   location: https://github.com/supki/envparse
+
+source-repository this
+  type:     git
+  location: https://github.com/supki/envparse
+  tag:      0.2.0
 
 library
   default-language:
diff --git a/example/Main.hs b/example/Main.hs
--- a/example/Main.hs
+++ b/example/Main.hs
@@ -24,5 +24,5 @@
 
 hello :: IO Hello
 hello = Env.parse (header "envparse example") $
-  Hello <$> var (str <=< nonempty) "NAME" (help "Target for the greeting")
-        <*> switch "QUIET" (help "Whether to actually print the greeting")
+  Hello <$> var (str <=< nonempty) "NAME"  (help "Target for the greeting")
+        <*> switch                 "QUIET" (help "Whether to actually print the greeting")
diff --git a/src/Env.hs b/src/Env.hs
--- a/src/Env.hs
+++ b/src/Env.hs
@@ -1,5 +1,5 @@
 {-# LANGUAGE Safe #-}
--- | Here's a simple example
+-- | Here's a simple example of a program that uses @envparse@'s parser:
 --
 -- @
 -- module Main (main) where
@@ -10,7 +10,7 @@
 -- data Hello = Hello { name :: String, quiet :: Bool }
 --
 -- hello :: IO Hello
--- hello = 'Env.parse' ('header' \"envparse example\") $
+-- hello = Env.'parse' ('header' \"envparse example\") $
 --   Hello \<$\> 'var' ('str' <=< 'nonempty') \"NAME\"  ('help' \"Target for the greeting\")
 --         \<*\> 'switch'                 \"QUIET\" ('help' \"Whether to actually print the greeting\")
 --
@@ -20,14 +20,37 @@
 --   unless quiet $
 --     putStrLn (\"Hello, \" ++ name ++ \"!\")
 -- @
+--
+-- The @NAME@ environment variable is mandatory and contains the name of the person to
+-- greet. @QUIET@, on the other hand, is an optional boolean flag, false by default, that
+-- decides whether the greeting should be silent.
+--
+-- If the @NAME@ variable is undefined in the environment then running the program will
+-- result in the following help text:
+--
+-- @
+-- envparse example
+--
+-- Available environment variables:
+--
+--   NAME                   Target for the greeting
+--   QUIET                  Whether to actually print the
+--                          greeting
+--
+-- Parsing errors:
+--
+--   NAME is missing
+-- @
 module Env
   ( parse
+  , parseOr
   , Parser
   , Mod
   , Info
   , header
   , desc
   , footer
+  , prefixed
   , var
   , Var
   , Reader
@@ -50,7 +73,7 @@
   , asum
   -- * Testing
   -- $testing
-  , parseTest
+  , parsePure
   ) where
 
 import           Control.Applicative
@@ -72,22 +95,31 @@
 -- what you want them to do
 
 
--- | Parse the environment
+-- | Parse the environment or die
 --
--- Prints the help text and exits with @EXIT_FAILURE@ if it encounters a parse error
+-- Prints the help text and exits with @EXIT_FAILURE@ on encountering a parse error.
 --
 -- @
--- >>> parse ('header' \"env-parse 0.1.0\") ('var' 'str' \"USER\" ('def' \"nobody\"))
+-- >>> parse ('header' \"env-parse 0.2.0\") ('var' 'str' \"USER\" ('def' \"nobody\"))
 -- @
 parse :: Mod Info a -> Parser a -> IO a
-parse i p = either (die . helpDoc i p) return . static p =<< getEnvironment
+parse m = fmap (either (\_ -> error "absurd") id) . parseOr die m
 
+-- | Try to parse the environment
+--
+-- Use this if simply dying on failure (the behavior of 'parse') is inadequate for your needs.
+parseOr :: (String -> IO a) -> Mod Info b -> Parser b -> IO (Either a b)
+parseOr f m p = traverseLeft f . parsePure m p =<< getEnvironment
+
 die :: String -> IO a
 die m = do IO.hPutStrLn IO.stderr m; exitFailure
 
--- | Parse a static environment
-parseTest :: Parser a -> [(String, String)] -> Maybe a
-parseTest p = hush . static p
+-- | Try to parse a pure environment
+parsePure :: Mod Info a -> Parser a -> [(String, String)] -> Either String a
+parsePure (Mod f) p = mapLeft (helpDoc (f defaultInfo) p) . static p
 
-hush :: Either a b -> Maybe b
-hush = either (const Nothing) Just
+mapLeft :: (a -> b) -> Either a t -> Either b t
+mapLeft f = either (Left . f) Right
+
+traverseLeft :: Applicative f => (a -> f b) -> Either a t -> f (Either b t)
+traverseLeft f = either (fmap Left . f) (pure . Right)
diff --git a/src/Env/Free.hs b/src/Env/Free.hs
--- a/src/Env/Free.hs
+++ b/src/Env/Free.hs
@@ -1,12 +1,15 @@
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE ScopedTypeVariables #-}
--- @Alt F@ is the free 'Alternative' functor on @F@
+-- | @Alt F@ is the free 'Alternative' functor on @F@
 module Env.Free
   ( Alt(..)
   , liftAlt
   , runAlt
   , foldAlt
+  , hoistAlt
+  -- * Debug
+  , inspect
   ) where
 
 import Control.Applicative (Applicative(..), Alternative(..))
@@ -18,14 +21,22 @@
   Pure :: a -> Alt f a
   Ap   :: Alt f (a -> b) -> Alt f a -> Alt f b
   Alt  :: Alt f a -> Alt f a -> Alt f a
-  Fun  :: f a -> Alt f a
+  Lift :: f a -> Alt f a
 
+-- | Print the free structure
+inspect :: Alt f a -> String
+inspect Nope      = "Nope"
+inspect (Pure _)  = "Pure _"
+inspect (Ap f x)  = concat ["(", inspect f, ") <*> (", inspect x, ")"]
+inspect (Alt x y) = concat ["(", inspect x, ") <|> (", inspect y, ")"]
+inspect (Lift _)  = "Lift _"
+
 instance Functor f => Functor (Alt f) where
   fmap _ Nope      = Nope
   fmap f (Pure a)  = Pure (f a)
   fmap f (Ap a v)  = Ap (fmap (f .) a) v
   fmap f (Alt a b) = Alt (fmap f a) (fmap f b)
-  fmap f (Fun a)   = Fun (fmap f a)
+  fmap f (Lift a)  = Lift (fmap f a)
 
 instance Functor f => Applicative (Alt f) where
   pure = Pure
@@ -37,7 +48,7 @@
 
 
 liftAlt :: f a -> Alt f a
-liftAlt = Fun
+liftAlt = Lift
 
 runAlt :: forall f g a. Alternative g => (forall x. f x -> g x) -> Alt f a -> g a
 runAlt u = go where
@@ -46,10 +57,13 @@
   go (Pure a)  = pure a
   go (Ap f x)  = go f <*> go x
   go (Alt s t) = go s <|> go t
-  go (Fun x)   = u x
+  go (Lift x)  = u x
 
 foldAlt :: Monoid p => (forall a. f a -> p) -> Alt f b -> p
 foldAlt f = unMon . runAlt (Mon . f)
+
+hoistAlt :: forall f g b. Functor g => (forall a. f a -> g a) -> Alt f b -> Alt g b
+hoistAlt nat = runAlt (Lift . nat)
 
 
 -- | The 'Alternative' functor induced by the 'Monoid'
diff --git a/src/Env/Help.hs b/src/Env/Help.hs
--- a/src/Env/Help.hs
+++ b/src/Env/Help.hs
@@ -12,16 +12,15 @@
 import           Env.Parse
 
 
-helpDoc :: Mod Info a -> Parser a -> [Error] -> String
-helpDoc (Mod f) p fs = intercalate "\n\n" . catMaybes $
-  [ infoHeader
-  , fmap (intercalate "\n" . splitWords 50) infoDesc
-  , Just "Available environment variables:"
-  , Just (intercalate "\n" (helpParserDoc p))
-  , fmap (intercalate "\n" . splitWords 50) infoFooter
-  ] ++ map Just (helpFailuresDoc fs)
- where
-  Info { infoHeader, infoDesc, infoFooter } = f defaultInfo
+helpDoc :: Info a -> Parser b -> [Error] -> String
+helpDoc Info { infoHeader, infoDesc, infoFooter } p fs =
+  intercalate "\n\n" . catMaybes $
+    [ infoHeader
+    , fmap (intercalate "\n" . splitWords 50) infoDesc
+    , Just "Available environment variables:"
+    , Just (intercalate "\n" (helpParserDoc p))
+    , fmap (intercalate "\n" . splitWords 50) infoFooter
+    ] ++ map Just (helpFailuresDoc fs)
 
 helpParserDoc :: Parser a -> [String]
 helpParserDoc = concat . Map.elems . foldAlt (\v -> Map.singleton (varfName v) (helpVarfDoc v)) . unParser
diff --git a/src/Env/Parse.hs b/src/Env/Parse.hs
--- a/src/Env/Parse.hs
+++ b/src/Env/Parse.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE DeriveFunctor #-}
 {-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE ViewPatterns #-}
 module Env.Parse
   ( Parser(..)
   , VarF(..)
@@ -11,6 +12,7 @@
   , header
   , desc
   , footer
+  , prefixed
   , var
   , Var(..)
   , defaultVar
@@ -37,12 +39,11 @@
 import           Env.Val
 
 
-static :: Parser a -> [(String, String)] -> Either [Error] a
-static (Parser p) xs = toEither (runAlt go p)
+static :: Parser b -> [(String, String)] -> Either [Error] b
+static (Parser p) (Map.fromList -> env) =
+  toEither (runAlt go p)
  where
-  go v = maybe id (\d x -> x <|> pure d) (varfDef v) (fromEither (readVar v =<< lookupVar v ys))
-
-  ys = Map.fromList xs
+  go v = maybe id (\d x -> x <|> pure d) (varfDef v) (fromEither (readVar v =<< lookupVar v env))
 
 lookupVar :: VarF a -> Map String String -> Either [Error] String
 lookupVar v = note [ENoExistError (varfName v)] . Map.lookup (varfName v)
@@ -69,7 +70,12 @@
   empty = Parser empty
   Parser f <|> Parser x = Parser (f <|> x)
 
+-- | The string to prepend to the name of every declared environment variable
+prefixed :: String -> Parser a -> Parser a
+prefixed pre =
+  Parser . hoistAlt (\v -> v { varfName = pre ++ varfName v }) . unParser
 
+
 data Error
   = ParseError String String
   | ENoExistError String
@@ -151,16 +157,16 @@
 
 -- | Parser's metadata
 data Info a = Info
-  { infoHeader :: Maybe String
-  , infoDesc   :: Maybe String
-  , infoFooter :: Maybe String
+  { infoHeader   :: Maybe String
+  , infoDesc     :: Maybe String
+  , infoFooter   :: Maybe String
   }
 
 defaultInfo :: Info a
 defaultInfo = Info
-  { infoHeader = Nothing
-  , infoDesc   = Nothing
-  , infoFooter = Nothing
+  { infoHeader   = Nothing
+  , infoDesc     = Nothing
+  , infoFooter   = Nothing
   }
 
 -- | A help text header (it usually includes an application name and version)
