diff --git a/Data/Range/Algebra.hs b/Data/Range/Algebra.hs
--- a/Data/Range/Algebra.hs
+++ b/Data/Range/Algebra.hs
@@ -9,6 +9,27 @@
 -- evaluate them all at once. This is not only useful for efficiency but for
 -- parsing too. Build up @RangeExpr@'s whenever you wish to perform multiple
 -- operations in a row, and evaluate it in one step to be as efficient as possible.
+--
+-- __Note:__ This module is based on F-Algebras to do much of the heavy conceptual
+-- lifting. If you have never seen F-Algebras before then I highly recommend reading
+-- through <https://www.schoolofhaskell.com/user/bartosz/understanding-algebras this introductory content>
+-- from the School of Haskell.
+--
+-- == Examples
+--
+-- A simple example of using this module would look like this:
+--
+-- @
+-- ghci> import qualified Data.Range.Algebra as A
+-- ghci> (A.eval . A.invert $ A.const [SingletonRange 5]) :: [Range Integer]
+-- [LowerBoundRange 6,UpperBoundRange 4]
+-- (0.01 secs, 597,656 bytes)
+-- ghci>
+-- @
+--
+-- You can also use this module to evaluate range predicates.
+--
+--
 module Data.Range.Algebra
   ( RangeExpr
     -- ** Operations
@@ -50,6 +71,7 @@
 -- of a range, so that a range expression of the same type can be evaluated, yielding
 -- that representation.
 class RangeAlgebra a where
+  -- | This function is used to convert your built expressions into ranges.
   eval :: Algebra RangeExpr a
 
 -- | Multiple ranges represented by a list of disjoint ranges.
diff --git a/Data/Range/Algebra/Internal.hs b/Data/Range/Algebra/Internal.hs
--- a/Data/Range/Algebra/Internal.hs
+++ b/Data/Range/Algebra/Internal.hs
@@ -49,6 +49,9 @@
 newtype RangeExpr a = RangeExpr { getFree :: Free RangeExprF a }
   deriving (Show, Eq, Functor)
 
+-- | This is an F-Algebra. You don't need to know what this is in order to be able
+-- to use this module, but, if you are interested you can
+-- <https://www.schoolofhaskell.com/user/bartosz/understanding-algebras read more on School of Haskell>.
 type Algebra f a = f a -> a
 
 rangeMergeAlgebra :: (Ord a, Enum a) => Algebra RangeExprF (RangeMerge a)
diff --git a/Data/Range/NestedRange.hs b/Data/Range/NestedRange.hs
--- a/Data/Range/NestedRange.hs
+++ b/Data/Range/NestedRange.hs
@@ -1,24 +1,69 @@
 {-# LANGUAGE Safe #-}
 
 -- | Nested Ranges are common in practical usage. They appear in such forms as library
--- version numbers ("Version 1.4.5.6" for example). And it is very useful to be able to
--- compare these ranges to one another. This module exists for the purpose of allowing
--- these comparisons between nested ranges. The module builds upon the basic range concept
--- from other parts of this library.
-module Data.Range.NestedRange where
+-- version numbers ("Version 1.4.5.6" for example).
+--
+-- It is very useful to be able to compare these ranges to one another. This module exists
+-- for the purpose of allowing these comparisons between nested ranges. The module builds
+-- upon the basic range concept from other parts of this library.
+module Data.Range.NestedRange
+  ( NestedRange(..)
+  , fromVersion
+  , inNestedRange
+  ) where
 
 import Data.Range.Range
+import Data.Version
 
 -- | The Nested Range is a structure that in a nested form of many ranges where there can
 -- be multiple ranges at every level.
+--
+-- For example, saying that you require a minimum version of 1.2.3 could be represented as:
+--
+-- @
+-- NestedRange [[LowerBoundRange 1],[LowerBoundRange 2],[LowerBoundRange 3]]
+-- @
 data NestedRange a = NestedRange [[Range a]]
-
+  deriving(Eq, Show)
 
 -- I wanted to know if a nested number of elements are in a given range. That way I can
 -- just immediately run a single function and tell things about ranges.
 
 -- | Given a list of nested values and a nested range tell us wether the nested value
 -- exists inside the nested range.
+--
+-- == Examples
+--
+-- In a simple case:
+--
+-- @
+-- ghci> inNestedRange [2, 8, 3] (NestedRange [[SpanRange 1 2]] :: NestedRange Integer)
+-- True
+-- (0.01 secs, 558,400 bytes)
+-- ghci>
+-- @
+--
+-- Not in the bounds:
+--
+-- @
+-- ghci> inNestedRange [2, 8, 3] (NestedRange [[SpanRange 1 2], [UpperBoundRange 7]] :: NestedRange Integer)
+-- False
+-- (0.00 secs, 558,896 bytes)
+-- ghci>
+-- @
+--
+-- For something based on Data.Version:
+--
+-- @
+-- ghci> version = Version [2, 8, 3] []
+-- ghci> upperBound = Version [2, 7] []
+-- ghci> inNestedRange (versionBranch version) (fromVersion UpperBoundRange upperBound)
+-- False
+-- ghci>
+-- ghci> inNestedRange (versionBranch version) (fromVersion LowerBoundRange upperBound)
+-- True
+-- ghci>
+-- @
 inNestedRange :: Ord a => [a] -> NestedRange a -> Bool
 inNestedRange values (NestedRange ranges) = go values ranges
    where
@@ -27,3 +72,16 @@
       go _  [] = True -- If you have already found the values you have to be in range then they are
       go [] _  = False -- If you have not fully matched it yet then it is not in range.
       go (value : vs) (range : rs) = inRanges range value && go vs rs
+
+-- | This method converts the "Data.Version" datatype into a "NestedRange".
+--
+-- For example:
+--
+-- @
+-- ghci> fromVersion LowerBoundRange (Version [1, 2, 3] [])
+-- NestedRange [[LowerBoundRange 1],[LowerBoundRange 2],[LowerBoundRange 3]]
+-- (0.01 secs, 624,736 bytes)
+-- ghci>
+-- @
+fromVersion :: (Int -> Range Int) -> Version -> NestedRange Int
+fromVersion bound = NestedRange . fmap (return . bound) . versionBranch
diff --git a/Data/Range/Parser.hs b/Data/Range/Parser.hs
--- a/Data/Range/Parser.hs
+++ b/Data/Range/Parser.hs
@@ -1,17 +1,30 @@
 {-# LANGUAGE FlexibleContexts #-}
 
--- | It should not be unexpected that you will be given a string representation of some
--- ranges and you will need to parse them so that you can then do some further processing.
--- This parser exists in order to make the most common forms of range strings easy to
--- parse. It does not cover all cases however but you should not be too worried about
--- that because you should be able to write your own parser using parsec or Alex/Happy and
--- then you can convert everything that you parse into a RangeTree object for easier
--- processing.
-module Data.Range.Parser 
+-- | This package provides a simple range parser.
+--
+-- This range parser was designed to be a useful tool for CLI programs. For example, by
+-- default, this example depicts how the parser works:
+--
+-- @
+-- ghci> parseRanges "-5,8-10,13-15,20-" :: Either ParseError [Range Integer]
+-- Right [UpperBoundRange 5,SpanRange 8 10,SpanRange 13 15,LowerBoundRange 20]
+-- (0.01 secs, 681,792 bytes)
+-- ghci>
+-- @
+--
+-- And the * character translates to an infinite range. This is very useful for accepting
+-- ranges as input in CLI programs, but not as useful for parsing .cabal or package.json files.
+--
+-- To handle more complex parsing cases it is recommended that you use the ranges library
+-- in conjunction with parsec or Alex/Happy and convert the versions that you find into
+-- ranges.
+module Data.Range.Parser
    ( parseRanges
-   , ranges
+   , customParseRanges
    , RangeParserArgs(..)
    , defaultArgs
+   , ranges
+   , ParseError
    ) where
 
 import Text.Parsec
@@ -19,9 +32,8 @@
 
 import Data.Range.Range
 
--- | The arguments that are used, and can be modified, while parsing a standard range
--- string.
-data RangeParserArgs = Args 
+-- | These are the arguments that will be used when parsing a string as a range.
+data RangeParserArgs = Args
    { unionSeparator :: String -- ^ A separator that represents a union.
    , rangeSeparator :: String -- ^ A separator that separates the two halves of a range.
    , wildcardSymbol :: String -- ^ A separator that implies an unbounded range.
@@ -30,28 +42,34 @@
 
 -- | These are the default arguments that are used by the parser. Please feel free to use
 -- the default arguments for you own parser and modify it from the defaults at will.
-defaultArgs :: RangeParserArgs 
+defaultArgs :: RangeParserArgs
 defaultArgs = Args
    { unionSeparator = ","
    , rangeSeparator = "-"
    , wildcardSymbol = "*"
    }
 
--- | Given a string this function will either return a parse error back to the user or the
--- list of ranges that are represented by the parsed string.
+-- | Given a string, this function will either return a parse error back to the user or the
+-- list of ranges that are represented by the parsed string. Very useful for CLI programs
+-- that need to load ranges from a single-line string.
 parseRanges :: (Read a) => String -> Either ParseError [Range a]
 parseRanges = parse (ranges defaultArgs) "(range parser)"
 
+-- | If you disagree with the default characters for separating ranges then this function can
+-- be used to customise them, up to a point.
+customParseRanges :: Read a => RangeParserArgs -> String -> Either ParseError [Range a]
+customParseRanges args = parse (ranges args) "(range parser)"
+
 string_ :: Stream s m Char => String -> ParsecT s u m ()
 string_ x = string x >> return ()
 
--- | Given the parser arguments this returns a parser that is capable of parsing a list of
+-- | Given the parser arguments this returns a parsec parser that is capable of parsing a list of
 -- ranges.
 ranges :: (Read a) => RangeParserArgs -> Parser [Range a]
 ranges args = range `sepBy` (string $ unionSeparator args)
-   where 
+   where
       range :: (Read a) => Parser (Range a)
-      range = choice 
+      range = choice
          [ infiniteRange
          , spanRange
          , singletonRange
diff --git a/Data/Range/Range.hs b/Data/Range/Range.hs
--- a/Data/Range/Range.hs
+++ b/Data/Range/Range.hs
@@ -1,17 +1,20 @@
 {-# LANGUAGE Safe #-}
 
--- | This entire library is concerned with ranges and this module implements the absolute
--- basic range functions.
+-- | This module provides a simple api to access range functionality. It provides standard
+-- set operations on ranges, the ability to merge ranges together and, importantly, the ability
+-- to check if a value is within a range.
+--
+-- __Note:__ It is intended that you will read the documentation in this module from top to bottom.
 module Data.Range.Range (
       Range(..),
       inRange,
       inRanges,
       rangesOverlap,
       mergeRanges,
-      invert,
       union,
       intersection,
       difference,
+      invert,
       fromRanges
    ) where
 
@@ -21,23 +24,59 @@
 
 -- | Performs a set union between the two input ranges and returns the resultant set of
 -- ranges.
+--
+-- For example:
+--
+-- @
+-- ghci> union [SpanRange 1 10] [SpanRange 5 (15 :: Integer)]
+-- [SpanRange 1 15]
+-- (0.00 secs, 587,152 bytes)
+-- ghci>
+-- @
 union :: (Ord a, Enum a) => [Range a] -> [Range a] -> [Range a]
 union a b = Alg.eval $ Alg.union (Alg.const a) (Alg.const b)
 {-# INLINE union #-}
 
 -- | Performs a set intersection between the two input ranges and returns the resultant set of
 -- ranges.
+--
+-- For example:
+--
+-- @
+-- ghci> intersection [SpanRange 1 10] [SpanRange 5 (15 :: Integer)]
+-- [SpanRange 5 10]
+-- (0.00 secs, 584,616 bytes)
+-- ghci>
+-- @
 intersection :: (Ord a, Enum a) => [Range a] -> [Range a] -> [Range a]
 intersection a b = Alg.eval $ Alg.intersection (Alg.const a) (Alg.const b)
 {-# INLINE intersection #-}
 
 -- | Performs a set difference between the two input ranges and returns the resultant set of
 -- ranges.
+--
+-- For example:
+--
+-- @
+-- ghci> difference [SpanRange 1 10] [SpanRange 5 (15 :: Integer)]
+-- [SpanRange 1 4]
+-- (0.00 secs, 590,424 bytes)
+-- ghci>
+-- @
 difference :: (Ord a, Enum a) => [Range a] -> [Range a] -> [Range a]
 difference a b = Alg.eval $ Alg.difference (Alg.const a) (Alg.const b)
 {-# INLINE difference #-}
 
 -- | An inversion function, given a set of ranges it returns the inverse set of ranges.
+--
+-- For example:
+--
+-- @
+-- ghci> invert [SpanRange 1 10, SpanRange 15 (20 :: Integer)]
+-- [LowerBoundRange 21,UpperBoundRange 0,SpanRange 11 14]
+-- (0.00 secs, 623,456 bytes)
+-- ghci>
+-- @
 invert :: (Ord a, Enum a) => [Range a] -> [Range a]
 invert = Alg.eval . Alg.invert . Alg.const
 {-# INLINE invert #-}
@@ -60,6 +99,24 @@
 
 -- | Given a range and a value it will tell you wether or not the value is in the range.
 -- Remember that all ranges are inclusive.
+--
+-- The primary value of this library is performance and this method can be used to show
+-- this quite clearly. For example, you can try and approximate basic range functionality
+-- with "Data.List.elem" so we can generate an apples to apples comparison in GHCi:
+--
+-- @
+-- ghci> :set +s
+-- ghci> elem (10000000 :: Integer) [1..10000000]
+-- True
+-- (0.26 secs, 720,556,888 bytes)
+-- ghci> inRange (SpanRange 1 10000000) (10000000 :: Integer)
+-- True
+-- (0.00 secs, 557,656 bytes)
+-- ghci>
+-- @
+--
+-- As you can see, this function is significantly more performant, in both speed and memory,
+-- than using the elem function.
 inRange :: (Ord a) => Range a -> a -> Bool
 inRange (SingletonRange a) value = value == a
 inRange (SpanRange x y) value = isBetween value (x, y)
@@ -72,30 +129,79 @@
 inRanges :: (Ord a) => [Range a] -> a -> Bool
 inRanges rs a = any (`inRange` a) rs
 
--- | When you create a range there may be overlaps in your ranges. However, for the sake
--- of efficiency you probably want the list of ranges with no overlaps. The mergeRanges
--- function takes a set of ranges and returns the same set specified by the minimum number
--- of Range objects. A useful function for cleaning up your ranges. Please note that, if
--- you use any of the other operations on sets of ranges like invert, union and
--- intersection then this is automatically done for you. Which means that a function like
--- this is redundant: mergeRanges . intersection
+-- | An array of ranges may have overlaps; this function will collapse that array into as few
+-- Ranges as possible. For example:
+--
+-- @
+-- ghci> mergeRanges [LowerBoundRange 12, SpanRange 1 10, SpanRange 5 (15 :: Integer)]
+-- [LowerBoundRange 1]
+-- (0.01 secs, 588,968 bytes)
+-- ghci>
+-- @
+--
+-- As you can see, the mergeRanges method collapsed multiple ranges into a single range that
+-- still covers the same surface area.
+--
+-- This may be useful for a few use cases:
+--
+--  * You are hyper concerned about performance and want to have the minimum number of ranges
+--    for comparison in the inRanges function.
+--  * You wish to display ranges to a human and want to show the minimum number of ranges to
+--    avoid having to make people perform those calculations themselves.
+--
+-- Please note that the use of any of the operations on sets of ranges like invert, union and
+-- intersection will have the same behaviour as mergeRanges as a side effect. So, for example,
+-- this is redundant:
+--
+-- @
+-- mergeRanges . intersection []
+-- @
 mergeRanges :: (Ord a, Enum a) => [Range a] -> [Range a]
-mergeRanges = Alg.eval . Alg.const
+mergeRanges = Alg.eval . Alg.union (Alg.const []) . Alg.const
 {-# INLINE mergeRanges #-}
 
--- | A set of ranges represents a collection of real values without actually instantiating
--- those values. This allows you to have infinite ranges. However, sometimes you wish to
--- actually get the values that your range represents, or even get a sample set of the
--- values. This function generates as many of the values that belong to your range as you
--- like.
+-- | Instantiate all of the values in a range.
+--
+-- __Warning__: This method is meant as a convenience method, it is not efficient.
+--
+-- A set of ranges represents a collection of real values without actually instantiating
+-- those values. Not instantiating ranges, allows the range library to support infinite
+-- ranges and be super performant.
+--
+-- However, sometimes you actually want to get the values that your range represents, or even
+-- get a sample set of the values. This function generates as many of the values that belong
+-- to your range as you like.
+--
+-- Because ranges can be infinite, it is highly recommended to combine this method with something like
+-- "Data.List.take" to avoid an infinite recursion.
+--
+-- == Examples
+--
+-- A simple span:
+--
+-- @
+-- ghci> take 5 . fromRanges $ [SpanRange 1 10 :: Range Integer]
+-- [1,2,3,4,5]
+-- (0.01 secs, 566,016 bytes)
+-- ghci>
+-- @
+--
+-- An infinite range:
+--
+-- @
+-- ghci> take 5 . fromRanges $ [InfiniteRange :: Range Integer]
+-- [0,1,-1,2,-2]
+-- (0.00 secs, 566,752 bytes)
+-- ghci>
+-- @
 fromRanges :: (Ord a, Enum a) => [Range a] -> [a]
-fromRanges = concatMap fromRange
+fromRanges = takeEvenly . fmap fromRange . mergeRanges
    where
       fromRange range = case range of
          SingletonRange x -> [x]
          SpanRange a b -> [a..b]
          LowerBoundRange x -> iterate succ x
          UpperBoundRange x -> iterate pred x
-         InfiniteRange -> zero : takeEvenly (tail $ iterate succ zero) (tail $ iterate pred zero)
+         InfiniteRange -> zero : takeEvenly [tail $ iterate succ zero, tail $ iterate pred zero]
             where
                zero = toEnum 0
diff --git a/Data/Range/RangeInternal.hs b/Data/Range/RangeInternal.hs
--- a/Data/Range/RangeInternal.hs
+++ b/Data/Range/RangeInternal.hs
@@ -3,7 +3,6 @@
 module Data.Range.RangeInternal where
 
 import Data.Maybe (catMaybes)
---import Data.Ord (comparing)
 
 import Data.Range.Data
 import Data.Range.Spans
@@ -14,7 +13,7 @@
  - functions so that we can reason about what we are given.
  -
  - RangeMerge assumptions:
- - * The span ranges will never overlap the bounds. 
+ - * The span ranges will never overlap the bounds.
  - * The span ranges are always sorted in ascending order by the first element.
  - * The lower and upper bounds never overlap in such a way to make it an infinite range.
  -}
@@ -48,8 +47,8 @@
 exportRangeMerge rm = putAll rm
    where
       putAll IRM = [InfiniteRange]
-      putAll (RM lb up spans) = 
-         putLowerBound lb ++ putUpperBound up ++ putSpans spans
+      putAll (RM lb up spans) =
+         putUpperBound up ++ putSpans spans ++ putLowerBound lb
 
       putLowerBound = maybe [] (return . LowerBoundRange)
       putUpperBound = maybe [] (return . UpperBoundRange)
@@ -64,7 +63,7 @@
 intersectSpansRM :: (Ord a) => RangeMerge a -> RangeMerge a -> RangeMerge a
 intersectSpansRM one two = RM Nothing Nothing newSpans
    where
-      newSpans = intersectSpans (spanRanges one) (spanRanges two) 
+      newSpans = intersectSpans (spanRanges one) (spanRanges two)
 
 intersectWith :: (Ord a) => (a -> (a, a) -> Maybe (a, a)) -> Maybe a -> [(a, a)] -> [(a, a)]
 intersectWith _ Nothing _ = []
@@ -88,14 +87,14 @@
    , largestUpperBound = newUpperBound
    , spanRanges = joinedSpans
    }
-   where 
+   where
       lowerOneSpans = intersectWith fixLower (largestLowerBound one) (spanRanges two)
       lowerTwoSpans = intersectWith fixLower (largestLowerBound two) (spanRanges one)
       upperOneSpans = intersectWith fixUpper (largestUpperBound one) (spanRanges two)
       upperTwoSpans = intersectWith fixUpper (largestUpperBound two) (spanRanges one)
-      intersectedSpans = intersectSpans (spanRanges one) (spanRanges two) 
+      intersectedSpans = intersectSpans (spanRanges one) (spanRanges two)
 
-      sortedResults = foldr1 insertionSortSpans 
+      sortedResults = foldr1 insertionSortSpans
          [ lowerOneSpans
          , lowerTwoSpans
          , upperOneSpans
@@ -109,10 +108,10 @@
       newLowerBound = calculateNewBound largestLowerBound max one two
       newUpperBound = calculateNewBound largestUpperBound min one two
 
-      calculateNewBound 
-         :: (Ord a) 
-         => (RangeMerge a -> Maybe a) 
-         -> (a -> a -> a) 
+      calculateNewBound
+         :: (Ord a)
+         => (RangeMerge a -> Maybe a)
+         -> (a -> a -> a)
          -> RangeMerge a -> RangeMerge a -> Maybe a
       calculateNewBound ext comp one two = case (ext one, ext two) of
          (Just x, Just y) -> Just $ comp x y
@@ -123,17 +122,17 @@
 calculateBoundOverlap one two = catMaybes [oneWay, secondWay]
    where
       oneWay = case (largestLowerBound one, largestUpperBound two) of
-         (Just x, Just y) -> if y >= x 
+         (Just x, Just y) -> if y >= x
             then Just (x, y)
             else Nothing
          _ -> Nothing
 
       secondWay = case (largestLowerBound two, largestUpperBound one) of
-         (Just x, Just y) -> if y >= x 
+         (Just x, Just y) -> if y >= x
             then Just (x, y)
             else Nothing
          _ -> Nothing
-      
+
 unionRangeMerges :: (Ord a, Enum a) => RangeMerge a -> RangeMerge a -> RangeMerge a
 unionRangeMerges IRM _ = IRM
 unionRangeMerges _ IRM = IRM
@@ -141,10 +140,10 @@
    where
       filterOne = foldr filterLowerBound boundedRM joinedSpans
       filterTwo = foldr filterUpperBound (filterOne { spanRanges = [] }) (spanRanges filterOne)
-      
+
       infiniteCheck :: (Ord a, Enum a) => RangeMerge a -> RangeMerge a
       infiniteCheck IRM = IRM
-      infiniteCheck rm@(RM (Just x) (Just y) _) = if x <= succ y 
+      infiniteCheck rm@(RM (Just x) (Just y) _) = if x <= succ y
          then IRM
          else rm
       infiniteCheck rm = rm
@@ -161,10 +160,10 @@
          , spanRanges = []
          }
 
-      calculateNewBound 
-         :: (Ord a) 
-         => (RangeMerge a -> Maybe a) 
-         -> (a -> a -> a) 
+      calculateNewBound
+         :: (Ord a)
+         => (RangeMerge a -> Maybe a)
+         -> (a -> a -> a)
          -> RangeMerge a -> RangeMerge a -> Maybe a
       calculateNewBound ext comp one two = case (ext one, ext two) of
          (Just x, Just y) -> Just $ comp x y
@@ -174,7 +173,7 @@
 filterLowerBound :: (Ord a, Enum a) => (a, a) -> RangeMerge a -> RangeMerge a
 filterLowerBound _ IRM = IRM
 filterLowerBound a rm@(RM Nothing _ _) = rm { spanRanges = a : spanRanges rm }
-filterLowerBound s@(lower, _) rm@(RM (Just lowestBound) _ _) = 
+filterLowerBound s@(lower, _) rm@(RM (Just lowestBound) _ _) =
    case boundCmp lowestBound s of
       GT -> rm { spanRanges = s : spanRanges rm }
       LT -> rm
@@ -196,7 +195,7 @@
 
 appendSpanRM :: (Ord a, Enum a) => (a, a) -> RangeMerge a -> RangeMerge a
 appendSpanRM _ IRM = IRM
-appendSpanRM sp@(lower, higher) rm = 
+appendSpanRM sp@(lower, higher) rm =
    if (newUpper, newLower) == (lub, llb) && isLower lower newLower && (Just higher) > newUpper
       then newRangesRM
          { spanRanges = sp : spanRanges rm
@@ -205,7 +204,7 @@
          { spanRanges = spanRanges rm
          }
    where
-      newRangesRM = rm 
+      newRangesRM = rm
          { largestLowerBound = newLower
          , largestUpperBound = newUpper
          }
@@ -257,7 +256,7 @@
          Just upper -> [(succ upper, newUpperValue)]
       lowerSpan = case largestLowerBound rm of
          Nothing -> []
-         Just lower -> [(newLowerValue, pred lower)] 
+         Just lower -> [(newLowerValue, pred lower)]
 
       betweenSpans = invertSpans . spanRanges $ rm
 
@@ -272,7 +271,7 @@
 {-
 intersectSpansRM :: (Ord a) => RangeMerge a -> (a, a) -> [(a, a)]
 intersectSpansRM rm sp@(lower, upper) = intersectedSpans
-   where 
+   where
       spans = spanRanges rm
       intersectedSpans = catMaybes $ map (intersectCompareSpan sp) spans
 
diff --git a/Data/Range/Util.hs b/Data/Range/Util.hs
--- a/Data/Range/Util.hs
+++ b/Data/Range/Util.hs
@@ -2,6 +2,8 @@
 
 module Data.Range.Util where
 
+import Data.Maybe (catMaybes)
+
 -- This module is supposed to contain all of the functions that are required by the rest
 -- of the code but could be easily pulled into separate and completely non-related
 -- codebases or libraries.
@@ -9,7 +11,7 @@
 insertionSort :: (Ord a) => (a -> a -> Ordering) -> [a] -> [a] -> [a]
 insertionSort comp xs ys = go xs ys
    where
-      go (f : fs) (s : ss) = case comp f s of 
+      go (f : fs) (s : ss) = case comp f s of
          LT -> f : go fs (s : ss)
          EQ -> f : s : go fs ss
          GT -> s : go (f : fs) ss
@@ -19,11 +21,14 @@
 isBetween :: (Ord a) => a -> (a, a) -> Bool
 isBetween a (x, y) = (x <= a) && (a <= y)
 
-takeEvenly :: [a] -> [a] -> [a]
-takeEvenly (a : as) (b : bs) = a : b : takeEvenly as bs
-takeEvenly xs [] = xs
-takeEvenly [] xs = xs
-   
+takeEvenly :: [[a]] -> [a]
+takeEvenly [] = []
+takeEvenly xss = (catMaybes . map safeHead $ xss) ++ takeEvenly (filter (not . null) . map tail $ xss)
+
+safeHead :: [a] -> Maybe a
+safeHead [] = Nothing
+safeHead (x : _) = Just x
+
 pairs :: [a] -> [(a, a)]
 pairs [] = []
 pairs xs = zip xs (tail xs)
diff --git a/range.cabal b/range.cabal
--- a/range.cabal
+++ b/range.cabal
@@ -10,18 +10,23 @@
 -- PVP summary:      +-+------- breaking API changes
 --                   | | +----- non-breaking API additions
 --                   | | | +--- code changes with no API change
-version:             0.2.0.0
+version:             0.2.1.0
 
 -- A short (one-line) description of the package.
-synopsis:            This has a bunch of code for specifying and managing ranges in your code.
+synopsis:            An efficient and versatile range library.
 
 -- A longer description of the package.
-description:         range is built to allow you to use ranges in your code quickly and
-                     efficiently. There are many occasions where you will want to check if
-                     certain values are within a range and this library will make it
-                     trivial for you to do so. It also attempts to do so in the most
-                     efficient way possible.
+description:         The range library alows the use of performant and versatile ranges in your code.
+                     It supports bounded and unbounded ranges, ranges in a nested manner (like library
+                     versions), an efficient algebra of range computation and even a simplified interface
+                     for ranges for the common cases. This library is far more efficient than using the
+                     default Data.List functions to approximate range behaviour. Performance is the major
+                     value offering of this library.
 
+                     If this is your first time using this library it is highly recommended that you start
+                     with "Data.Range.Range"; it contains the basics of this library that meet most use
+                     cases.
+
 homepage:            https://bitbucket.org/robertmassaioli/range
 
 -- The license under which the package is released.
@@ -67,7 +72,7 @@
 
 
   -- Other library packages from which modules are imported.
-  build-depends:  base >= 4.5 && < 5
+  build-depends:  base >= 4.7 && < 5
                   , parsec >= 3
                   , free >=4.12
 
