diff --git a/semver.cabal b/semver.cabal
--- a/semver.cabal
+++ b/semver.cabal
@@ -1,5 +1,5 @@
 name:                  semver
-version:               0.1.2
+version:               0.2.0
 synopsis:              Representation, manipulation, and de/serialisation of Semantic Versions.
 homepage:              https://github.com/brendanhay/semver
 license:               OtherLicense
diff --git a/src/Data/SemVer.hs b/src/Data/SemVer.hs
--- a/src/Data/SemVer.hs
+++ b/src/Data/SemVer.hs
@@ -1,7 +1,5 @@
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE DeriveGeneric      #-}
-{-# LANGUAGE OverloadedStrings  #-}
-{-# LANGUAGE RecordWildCards    #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards   #-}
 
 -- Module      : Data.SemVer
 -- Copyright   : (c) 2014 Brendan Hay <brendan.g.hay@gmail.com>
@@ -17,56 +15,62 @@
 -- <http://semver.org>.
 --
 -- A canonical 'Version' type and functions representing behaviour as outlined
--- in the specification are defined alongside additional lenses,
+-- in the specification are defined alongside additional lenses, traversals,
 -- common manipulations, and serialisation primitives.
 module Data.SemVer
     (
     -- * Version
-      Identifier (..)
-    , Version    (..)
-    , defaultVersion
-
+      Version
+    -- ** Constructors
+    , version
+    , initial
     -- ** Lenses
+    -- $lenses
     , versionMajor
     , versionMinor
     , versionPatch
     , versionRelease
     , versionMeta
-
     -- ** Incrementing
+    -- $incrementing
     , incrementMajor
     , incrementMinor
     , incrementPatch
-
     -- ** Predicates
     , isDevelopment
     , isPublic
-
     -- ** Encoding
     , toString
     , toText
     , toLazyText
     , toBuilder
-
     -- ** Decoding
     , fromText
     , fromLazyText
     , parser
 
-    -- * Delimiters
-    , Delimiters (..)
-    , defaultDelimiters
+    -- * Identifiers
+    , Identifier
+    -- ** Constructors
+    , numeric
+    , textual
+    -- ** Prisms
+    , _Numeric
+    , _Textual
 
+    -- * Delimiters
+    -- $delimiters
+    , Delimiters
+    -- ** Constructor
+    , delimiters
     -- ** Lenses
     , delimMinor
     , delimPatch
     , delimRelease
     , delimMeta
     , delimIdent
-
     -- ** Encoding
     , toDelimitedBuilder
-
     -- ** Decoding
     , delimitedParser
     ) where
@@ -85,8 +89,6 @@
 import           Data.Text.Lazy.Builder     (Builder)
 import qualified Data.Text.Lazy.Builder     as Build
 import qualified Data.Text.Lazy.Builder.Int as Build
-import           Data.Typeable              (Typeable)
-import           GHC.Generics
 import           Prelude                    hiding (takeWhile)
 
 -- | A type representing an individual identifier from the release
@@ -95,11 +97,35 @@
 -- * The 'Ord' instance implements precedence according to the semantic version
 -- specification, with numeric identifiers being of /lower/ precedence than
 -- textual identifiers, otherwise lexicographic ordering is used.
+--
+-- The functions 'numeric' and 'textual' can be used to construct an 'Identifier'.
 data Identifier
     = INum  !Int
     | IText !Text
-      deriving (Eq, Read, Show, Generic, Typeable)
+      deriving (Eq, Show)
 
+-- | Safely construct a numeric identifier.
+numeric :: Int -> Identifier
+numeric = INum
+{-# INLINE numeric #-}
+
+-- | Construct an identifier from the given 'Text', returning 'Nothing' if
+-- neither a numeric or valid textual input is supplied.
+textual :: Text -> Maybe Identifier
+textual = either (const Nothing) Just
+    . parseOnly (identifierParser endOfInput <* endOfInput)
+{-# INLINE textual #-}
+
+_Numeric :: Applicative f => (Int -> f Int) -> Identifier -> f Identifier
+_Numeric f (INum x) = INum <$> f x
+_Numeric _ x        = pure x
+{-# INLINE _Numeric #-}
+
+_Textual :: Applicative f => (Text -> f Text) -> Identifier -> f Identifier
+_Textual f (IText x) = IText <$> f x
+_Textual _ x         = pure x
+{-# INLINE _Textual #-}
+
 instance Ord Identifier where
     compare a b = case (a, b) of
         (INum  x, INum  y) -> x `compare` y
@@ -111,31 +137,38 @@
     rnf (INum  n) = rnf n
     rnf (IText t) = rnf t
 
--- | A type representing a successfully decoded or constructed semantic version.
+-- | An opaque type representing a successfully decoded or constructed
+-- semantic version. See the related functions and lenses for modification and
+-- update.
 --
 -- * The 'Eq' instance represents exhaustive equality with all
 -- components considered.
 --
 -- * The 'Ord' instance implements the precedence rules from the semantic
--- version specification with metadata ('_versionMeta') being ignored.
+-- version specification with metadata being ignored.
 data Version = Version
     { _versionMajor   :: !Int
-     -- ^ The major version component.
     , _versionMinor   :: !Int
-      -- ^ The minor version component.
     , _versionPatch   :: !Int
-      -- ^ The patch level component.
     , _versionRelease :: [Identifier]
-      -- ^ A (potentially empty) list of release identifiers.
     , _versionMeta    :: [Identifier]
-      -- ^ A (potentially empty) list of metadata.
-    } deriving (Eq, Read, Show, Generic, Typeable)
+    } deriving (Eq, Show)
 
+-- | Smart constructor fully specifying all available version components.
+version :: Int          -- ^ Major version component.
+        -> Int          -- ^ Minor version component.
+        -> Int          -- ^ Patch version component.
+        -> [Identifier] -- ^ Release identifiers.
+        -> [Identifier] -- ^ Metadata identifiers.
+        -> Version
+version = Version
+{-# INLINE version #-}
+
 -- | A default 'Version' which can be used to signify initial development.
 --
 -- Note: Equivalent to @0.0.0@
-defaultVersion :: Version
-defaultVersion = Version 0 0 0 [] []
+initial :: Version
+initial = version 0 0 0 [] []
 
 instance Ord Version where
     compare a b = on compare versions a b <> on compare _versionRelease a b
@@ -154,18 +187,27 @@
         `seq` rnf _versionRelease
         `seq` rnf _versionMeta
 
+-- $lenses
+--
+-- Something about using lenses to construct versions and increments to update
+-- the version components due to the modification of all version according to spec
+
+-- | Lens for the major version component.
 versionMajor :: Functor f => (Int -> f Int) -> Version -> f Version
 versionMajor f x = (\y -> x { _versionMajor = y }) <$> f (_versionMajor x)
 {-# INLINE versionMajor #-}
 
+-- | Lens for minor version component.
 versionMinor :: Functor f => (Int -> f Int) -> Version -> f Version
 versionMinor f x = (\y -> x { _versionMinor = y }) <$> f (_versionMinor x)
 {-# INLINE versionMinor #-}
 
+-- | Lens for the patch version component.
 versionPatch :: Functor f => (Int -> f Int) -> Version -> f Version
 versionPatch f x = (\y -> x { _versionPatch = y }) <$> f (_versionPatch x)
 {-# INLINE versionPatch #-}
 
+-- | Lens for the list of release identifiers.
 versionRelease :: Functor f
                => ([Identifier] -> f [Identifier])
                -> Version
@@ -173,6 +215,7 @@
 versionRelease f x = (\y -> x { _versionRelease = y }) <$> f (_versionRelease x)
 {-# INLINE versionRelease #-}
 
+-- | Lens for the list of metadata identifiers.
 versionMeta :: Functor f
             => ([Identifier] -> f [Identifier])
             -> Version
@@ -180,15 +223,18 @@
 versionMeta f x = (\y -> x { _versionMeta = y }) <$> f (_versionMeta x)
 {-# INLINE versionMeta #-}
 
--- | A set of delimiters used to encode/decode a 'Version' and specifyc
+-- $delimiters
+--
+-- A set of delimiters is used to encode/decode a 'Version' and specify
 -- alternative serialisation strategies.
 --
--- Example: using alpha characters to encode the version as a valid
--- DNS CNAME, such as:
+-- Lenses can be used to modify the default delimiter set, as in the following
+-- example - using alpha characters to encode the version as a valid
+-- DNS CNAME:
 --
 -- @
 -- let Right v = fromText "1.2.3+40"
--- let alpha   = Delimiters \'m\' \'p\' \'r\' \'d\' \'i\'
+-- let alpha = delimiters & delimMajor .= \'m\' & delimPatch .= \'p\' & delimRelease .= \'r\' & delimMeta .= \'d\' & delimIdent .= \'i\'
 --
 -- Data.Text.Lazy.Builder.toLazyText (\"app01-\" <> toDelimitedBuilder alpha v <> \".dmz.internal\")
 -- @
@@ -201,13 +247,16 @@
 --
 -- Using the same 'Delimiters' set with 'delimitedParser' would ensure
 -- correct decoding behaviour.
+
+-- | An opaque set representing the seperators used to delimit semantic
+-- version components.
 data Delimiters = Delimiters
     { _delimMinor   :: !Char
     , _delimPatch   :: !Char
     , _delimRelease :: !Char
     , _delimMeta    :: !Char
     , _delimIdent   :: !Char
-    } deriving (Eq, Ord, Read, Show, Generic, Typeable)
+    } deriving (Eq, Ord, Show)
 
 -- | The default set of delimiters used in the semantic version specification.
 --
@@ -217,8 +266,8 @@
 -- @
 -- 1.2.3-alpha.1+sha.exp.12ab3d9
 -- @
-defaultDelimiters :: Delimiters
-defaultDelimiters = Delimiters
+delimiters :: Delimiters
+delimiters = Delimiters
     { _delimMinor   = '.'
     , _delimPatch   = '.'
     , _delimRelease = '-'
@@ -234,26 +283,36 @@
         `seq` rnf _delimMeta
         `seq` rnf _delimIdent
 
+-- | Lens for the minor version delimiter. Default: @.@
 delimMinor :: Functor f => (Char -> f Char) -> Delimiters -> f Delimiters
 delimMinor f x = (\y -> x { _delimMinor = y }) <$> f (_delimMinor x)
 {-# INLINE delimMinor #-}
 
+-- | Lens for the patch version delimiter. Default: @.@
 delimPatch :: Functor f => (Char -> f Char) -> Delimiters -> f Delimiters
 delimPatch f x = (\y -> x { _delimPatch = y }) <$> f (_delimPatch x)
 {-# INLINE delimPatch #-}
 
+-- | Lens for the release component delimiter. Default: @-@
 delimRelease :: Functor f => (Char -> f Char) -> Delimiters -> f Delimiters
 delimRelease f x = (\y -> x { _delimRelease = y }) <$> f (_delimRelease x)
 {-# INLINE delimRelease #-}
 
+-- | Lens for the metadata component delimiter. Default: @+@
 delimMeta :: Functor f => (Char -> f Char) -> Delimiters -> f Delimiters
 delimMeta f x = (\y -> x { _delimMeta = y }) <$> f (_delimMeta x)
 {-# INLINE delimMeta #-}
 
+-- | Lens for the individual identifier delimiter. Default: @.@
 delimIdent :: Functor f => (Char -> f Char) -> Delimiters -> f Delimiters
 delimIdent f x = (\y -> x { _delimIdent = y }) <$> f (_delimIdent x)
 {-# INLINE delimIdent #-}
 
+-- $increments
+--
+-- Mention the usage of increments to correctly adjust version components
+-- according to spec.
+
 -- | Increment the major component of a 'Version' by 1, resetting the minor
 -- and patch components.
 --
@@ -326,7 +385,7 @@
 -- Note: This is optimised for cases where you wish to use a 'String' and
 -- as such is faster than the semantically equivalent @unpack . toLazyText@.
 toString :: Version -> String
-toString = toMonoid (:[]) show Text.unpack defaultDelimiters
+toString = toMonoid (:[]) show Text.unpack delimiters
 
 -- | Convert a 'Version' to a strict 'Text' representation.
 --
@@ -345,7 +404,7 @@
 
 -- | Convert a 'Version' to a 'Builder'.
 toBuilder :: Version -> Builder
-toBuilder = toDelimitedBuilder defaultDelimiters
+toBuilder = toDelimitedBuilder delimiters
 
 -- | Convert a 'Version' to a 'Builder' using the specified 'Delimiters' set.
 toDelimitedBuilder :: Delimiters -> Version -> Builder
@@ -390,7 +449,7 @@
 
 -- | A greedy attoparsec 'Parser' which requires the entire 'Text' input to match.
 parser :: Parser Version
-parser = delimitedParser defaultDelimiters
+parser = delimitedParser delimiters
 
 -- | A greedy attoparsec 'Parser' using the specified 'Delimiters' set
 -- which requires the entire 'Text' input to match.
@@ -403,20 +462,18 @@
     <*> option [] (try (char _delimMeta)    *> identifiers)
     <*  endOfInput
   where
-    nonNegative :: (Show a, Integral a) => Parser a
-    nonNegative = do
-        n <- decimal
-        when (n < 0) $
-            fail ("Numeric value must be non-negative: " ++ show n)
-        return n
-
     identifiers :: Parser [Identifier]
-    identifiers = many (num <|> text)
+    identifiers = many (identifierParser $ void (char _delimIdent))
 
-    num = INum
-        <$> nonNegative
-        <*  (void (char _delimIdent) <|> endOfInput)
+identifierParser :: Parser () -> Parser Identifier
+identifierParser end = num <|> text
+  where
+    num  = INum  <$> nonNegative <* (end <|> endOfInput)
+    text = IText <$> takeWhile1 (inClass "0-9A-Za-z-") <* optional end
 
-    text = IText
-        <$> takeWhile1 (inClass "0-9A-Za-z-")
-        <*  optional (char _delimIdent)
+nonNegative :: (Show a, Integral a) => Parser a
+nonNegative = do
+    n <- decimal
+    when (n < 0) $
+        fail ("Numeric value must be non-negative: " ++ show n)
+    return n
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -59,7 +59,7 @@
 
 sv000, sv100, sv100alpha, sv100alpha1, sv101   :: Version
 sv110, sv200, sv123sha2ac, sv123beta1shaexpdc2 :: Version
-sv000               = defaultVersion
+sv000               = initial
 sv100               = sv "1.0.0"
 sv100alpha          = sv "1.0.0-alpha"
 sv100alpha1         = sv "1.0.0-alpha.1"
