diff --git a/src/Text/ParserCombinators/UU.hs b/src/Text/ParserCombinators/UU.hs
--- a/src/Text/ParserCombinators/UU.hs
+++ b/src/Text/ParserCombinators/UU.hs
@@ -1,6 +1,24 @@
+-- | The non-exported module "Text.ParserCombinators.UU.Examples" contains a list of examples of how to use the main functionality of this library: it demonstrates:
+--
+-- * how to write basic parsers
+--
+-- * how to to write ambiguous parsers
+--
+-- * how the error correction works
+--
+-- * how to fine tune your parsers to get rid of ambiguities
+--
+-- * how to use the monadic interface
+--
+-- * what kind of error messages you can get if you write erroneous parsers
+--
+
 module Text.ParserCombinators.UU ( module Text.ParserCombinators.UU.Core
                                  , module Text.ParserCombinators.UU.BasicInstances
-                                 , module Text.ParserCombinators.UU.Derived) where
+                                 , module Text.ParserCombinators.UU.Derived
+                                 , module Text.ParserCombinators.UU.Merge) where
 import Text.ParserCombinators.UU.Core
 import Text.ParserCombinators.UU.BasicInstances
 import Text.ParserCombinators.UU.Derived
+import Text.ParserCombinators.UU.Merge
+
diff --git a/src/Text/ParserCombinators/UU/BasicInstances.hs b/src/Text/ParserCombinators/UU/BasicInstances.hs
--- a/src/Text/ParserCombinators/UU/BasicInstances.hs
+++ b/src/Text/ParserCombinators/UU/BasicInstances.hs
@@ -20,9 +20,9 @@
                    | DeletedAtEnd String
 
 instance (Show pos) => Show (Error  pos) where 
- show (Inserted s pos expecting) = "--     Inserted " ++  s ++ " at position " ++ show pos ++  show_expecting  expecting 
- show (Deleted  t pos expecting) = "--     Deleted  " ++  t ++ " at position " ++ show pos ++  show_expecting  expecting 
- show (DeletedAtEnd t)           = "--     The token " ++ t ++ " was not consumed by the parsing process."
+ show (Inserted s pos expecting) = "-- >    Inserted " ++  s ++ " at position " ++ show pos ++  show_expecting  expecting 
+ show (Deleted  t pos expecting) = "-- >    Deleted  " ++  t ++ " at position " ++ show pos ++  show_expecting  expecting 
+ show (DeletedAtEnd t)           = "-- >    The token " ++ t ++ " was not consumed by the parsing process."
 
 show_errors = sequence_ . (map (putStrLn . show))
 
diff --git a/src/Text/ParserCombinators/UU/CHANGELOG.hs b/src/Text/ParserCombinators/UU/CHANGELOG.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/ParserCombinators/UU/CHANGELOG.hs
@@ -0,0 +1,53 @@
+-- | This module just contains the CHANGELOG
+--
+--  Version 2.4.1
+--
+--       * added the module Text.ParserCombinators.Merge for recognizing alternating sequences
+--
+--       * made @P st@ an instance of @`MonadPlus`@
+--
+--       * beautified Haddock documentation
+--
+-- | Version 2.4.0
+--
+--       * contains abstract interpretation for minimal lenth, in order to avoid recursive correction process
+--
+--       * idem for checking that no repeating combinators like pList are parameterised with possibly empty parsers
+--
+--       * lots of Haddcock doumentation in "Text.ParserCombinators.UU.Examples"
+--
+-- Version 2.3.4
+--
+--       * removed dependecies on impredictaive types, preparing for next GHC version
+--
+-- Version 2.3.3
+--
+--       * added `pMunch` which takes a Boolean function, and recognises the longest prefix for which the symbols match the predicate
+-- 
+--       * added the infix operator with piority 2 @\<?> :: P state a -> String -> P state a@ which replaces the list of expected symbols
+--         in error message by its right argument String
+--
+-- Version 2.3.2
+--
+--       * added microsteps, which can be used to disambiguate
+--
+-- Version 2.3.1
+--
+--       * fix for GHC 6.12, because of change in GADT definition handling
+--
+-- Versions above 2.2:
+--
+--       *  make use of type families
+--   
+--       *  contain a module with many list-based derived combinators
+--
+-- Versions above 2.1: 
+--       * based on Control.Applicative
+--
+--    Note that the basic parser interface will probably not change much when we add more features, but the calling conventions
+--    of the outer parser and the class structure upon which the parametrisation is based may change slightly
+
+module Text.ParserCombinators.UU.CHANGELOG () where
+
+
+dummy = undefined
diff --git a/src/Text/ParserCombinators/UU/Derived.hs b/src/Text/ParserCombinators/UU/Derived.hs
--- a/src/Text/ParserCombinators/UU/Derived.hs
+++ b/src/Text/ParserCombinators/UU/Derived.hs
@@ -9,6 +9,7 @@
 
 module Text.ParserCombinators.UU.Derived where
 import Text.ParserCombinators.UU.Core
+import Control.Monad
 
 -- | This module contains a large variety of combinators for list-lile structures. the extension @_ng@ indiactes that that varinat is the non-greedy variant.
 --   See the "Text.ParserCombinators.UU.Examples" module for some exmaples of their use.
@@ -27,10 +28,10 @@
 -- recognise the empty string, since this would make your parser ambiguous!!
 
 opt ::  P st a -> a -> P st a
-p `opt` v       =  p <<|> pure v 
+p `opt` v       = must_be_non_empty "opt" p (p <<|> pure v) 
 
 pMaybe :: P st a -> P st (Maybe a)
-pMaybe p = Just <$> p `opt` Nothing 
+pMaybe p = must_be_non_empty "pMaybe" p (Just <$> p `opt` Nothing) 
 
 pEither p q = Left <$> p <|> Right <$> q
                                                 
@@ -125,4 +126,9 @@
 -- | Parses any of the symbols in 'l'.
 pAnySym :: Provides st s s => [s] -> P st s
 pAnySym = pAny pSym 
+
+instance MonadPlus (P st) where
+  mzero = pFail
+  mplus = (<|>)
+
 
diff --git a/src/Text/ParserCombinators/UU/Examples.hs b/src/Text/ParserCombinators/UU/Examples.hs
--- a/src/Text/ParserCombinators/UU/Examples.hs
+++ b/src/Text/ParserCombinators/UU/Examples.hs
@@ -1,14 +1,11 @@
-{-# LANGUAGE  RankNTypes #-}
---              GADTs,
---              MultiParamTypeClasses,
---              FunctionalDependencies, 
---              FlexibleInstances, 
---              FlexibleContexts, 
---              UndecidableInstances,
---              NoMonomorphismRestriction
+{-# OPTIONS_HADDOCK  ignore-exports #-}
 module Text.ParserCombinators.UU.Examples where
 import Char
-import Text.ParserCombinators.UU
+import Text.ParserCombinators.UU.Core
+import Text.ParserCombinators.UU.Derived
+import Text.ParserCombinators.UU.BasicInstances
+import Text.ParserCombinators.UU.Merge
+import Control.Monad
 
 -- |We start out by defining the type of parser we want; by specifying the type of the state we resolve a lot of overloading
 
@@ -18,12 +15,11 @@
 run :: Show t =>  P (Str Char) t -> String -> IO ()
 run p inp = do  let r@(a, errors) =  parse ( (,) <$> p <*> pEnd) (listToStr inp)
                 putStrLn "--"
-                putStrLn "-- @"
-                putStrLn ("-- Result: " ++ show a)
+                putStrLn ("-- > Result: " ++ show a)
                 if null errors then  return ()
-                               else  do putStr ("-- Correcting steps: \n")
+                               else  do putStr ("-- > Correcting steps: \n")
                                         show_errors errors
-                putStrLn "-- @"
+                putStrLn "-- "
 
 
 -- | Our first two parsers are simple; one recognises a single 'a' character and the other one a single 'b'. Since we will use them later we 
@@ -34,42 +30,48 @@
 pb = lift <$> pSym 'b'
 lift a = [a]
 
--- | We can now run the parser @`pa`@ on input \"a\", which succeeds: 
+-- | We can now run the parser @`pa`@ on input \"a\", which succeeds:
 --
--- @ 
---   Result: \"a\"
--- @
+-- > run pa "a" 
+--
+-- > Result: "a"
+--
 
 test1 = run pa "a"
 
--- | If we   run the parser @`pa`@ on the empty input \"\", the expected symbol in inserted, that the position where it was inserted is reported, and
---   we get information about what was expected at that position:  @run pa \"\"@ 
+-- | If we   run the parser @`pa`@ on the empty input \"\", the expected symbol in inserted, 
+--   that the position where it was inserted is reported, and
+--   we get information about what was expected at that position: 
 --
--- @
--- Result: \"a\"
--- Correcting steps: 
---     Inserted 'a' at position 0 expecting 'a'
--- @
+-- > run pa ""
+--
+-- > Result: "a"
+-- > Correcting steps: 
+-- >    Inserted 'a' at position 0 expecting 'a'
+-- 
 
 test2 = run pa ""
 
--- | Now let's see what happens if we encounter an unexpected symbol, as in @run pa \"b\"@:
+-- | Now let's see what happens if we encounter an unexpected symbol, as in:
 --
--- @
--- Result: \"a\"
--- Correcting steps: 
---     Deleted  'b' at position 0 expecting 'a'
---     Inserted 'a' at position 1 expecting 'a'
--- @
+-- > run pa "b"
+--
+-- > Result: "a"
+-- > Correcting steps: 
+-- >    Deleted  'b' at position 0 expecting 'a'
+-- >    Inserted 'a' at position 1 expecting 'a'
+-- 
 
 test3 = run pa "b"
 
--- | The combinator @\<++>@ applies two parsers sequentially to the input and concatenates their results: @run (pa <++> pa) \"aa\"@:
+-- | The combinator @`<++>`@ applies two parsers sequentially to the input and concatenates their results:
 --
--- @
--- Result: \"aa\"
--- @
+-- > run (pa <++> pa) "aa"@:
+--
+-- > Result: "aa"
+-- 
 
+
 (<++>) :: Parser String -> Parser String -> Parser String
 p <++> q = (++) <$> p <*> q
 pa2 =   pa <++> pa
@@ -78,150 +80,164 @@
 test4 = run pa2 "aa"
 
 -- | The function @`pSym`@ is overloaded. The type of its argument determines how to interpret the argument. Thus far we have seen single characters, 
---   but we may pass ranges as well as argument: @\run (pList (pSym ('a','z'))) \"doaitse\"@
+--   but we may pass ranges as well as argument: 
 --
--- @
--- Result: "doaitse"
--- @
+-- > run (pList (pSym ('a','z'))) "doaitse"
+--
+--
+-- > Result: "doaitse"
+-- 
 
 test5 =  run  (pList (pSym ('a','z'))) "doaitse"
 paz = pList (pSym ('a', 'z'))
 
--- | An even more general instance of @`pSym`@ takes a triple as argument: a predicate, a string  indicating what is expected, 
---   and the value to insert if nothing can be recognised: @run (pSym (\t -> 'a' <= t && t <= 'z', \"'a'..'z'\", 'k')) \"v\"@
+-- | An even more general instance of @`pSym`@ takes a triple as argument: a predicate, 
+--   a string indicating what is expected, 
+--   and the value to insert if nothing can be recognised: 
+-- 
+-- > run (pSym (\t -> 'a' <= t && t <= 'z', "'a'..'z'", 'k')) "1"
 --
--- @
--- Result: 'k'
--- Correcting steps: 
---     Deleted  '1' at position 0 expecting 'a'..'z'
---     Inserted 'k' at position 1 expecting 'a'..'z'
--- @
+--
+-- > Result: 'k'
+-- > Correcting steps: 
+-- >    Deleted  '1' at position 0 expecting 'a'..'z'
+-- >    Inserted 'k' at position 1 expecting 'a'..'z'
+-- 
 
+
 test6 = run  paz' "1"
 paz' = pSym (\t -> 'a' <= t && t <= 'z', "'a'..'z'", 'k')
 
 -- | The parser `pCount` recognises a sequence of elements, throws away the results of the recognition process (@ \<$ @), and just returns the number of returned elements.
---   The choice combinator @\<\<|>@ indicates that prefernce is to be given to the left alternative if it can make progress. This enables us to specify greedy strategies:
---   @ run (pCount pa) \"aaaaa\"@
+--   The choice combinator @\<\<|>@ indicates that preference is to be given to the left alternative if it can make progress. This enables us to specify greedy strategies:
 --
--- @
--- Result: 5
--- @
+-- > run (pCount pa) "aaaaa"
+--
+-- > Result: 5
+-- 
 
 pCount p = (+1) <$ p <*> pCount p <<|> pReturn 0
 
 test7 = run (pCount pa) "aaaaa"
 
--- | The parsers are instance of the class Monad and hence we can use the result of a previous parser to construct a following one:  @run (do  {l <- pCount pa; pExact l pb}) \"aaacabbb\"@
+-- | The parsers are instance of the class Monad and hence we can use the 
+--   result of a previous parser to construct a following one:  
 --
--- @
--- Result: [\"b\",\"b\",\"b\",\"b\"]
--- Correcting steps: 
---     Deleted  'c' at position 3 expecting one of ['a', 'b']
---     Inserted 'b' at position 8 expecting 'b'
--- @
+-- > run (do  {l <- pCount pa; pExact l pb}) "aaacabbb"
+--
+-- > Result: ["b","b","b","b"]
+-- > Correcting steps: 
+-- >    Deleted  'c' at position 3 expecting one of ['a', 'b']
+-- >    Inserted 'b' at position 8 expecting 'b'
+-- 
 
 
 test8 = run (do  {l <- pCount pa; pExact l pb}) "aaacabbb"
 pExact 0 p = pReturn []
 pExact n p = (:) <$> p <*> pExact (n-1) p
 
--- | The function @`amb`@ converts an ambigous parser into one which returns all possible parses: @run (amb ( (++) <$> pa2 <*> pa3 <|> (++) <$> pa3 <*> pa2))  \"aaaaa\"@
+-- | The function @`amb`@ converts an ambigous parser into one which returns all possible parses: 
 --
--- @
--- Result: [\"aaaaa\",\"aaaaa\"]
--- @
+-- > run (amb ( (++) <$> pa2 <*> pa3 <|> (++) <$> pa3 <*> pa2))  "aaaaa"
+--
+-- > Result: ["aaaaa","aaaaa"]
+-- 
 
 test9 = run (amb ( (++) <$> pa2 <*> pa3 <|> (++) <$> pa3 <*> pa2))  "aaaaa"
 
--- | The applicative style makes it very easy to merge recognsition and computing a result. As an example we parse a sequence of nested well formed parentheses pairs a,d
---   compute the maximum nesting depth: @run ( max <$> pParens ((+1) <$> wfp) <*> wfp `opt` 0) \"((()))()(())\" @
+-- | The applicative style makes it very easy to merge recognsition and computing a result. 
+--   As an example we parse a sequence of nested well formed parentheses pairs and
+--   compute the maximum nesting depth with @`wfp`@: 
 --
--- @
--- Result: 3
--- @
+-- > run wfp "((()))()(())" 
+--
+-- > Result: 3
+-- 
 
 test10 = run wfp "((()))()(())"
+wfp :: Parser Int
 wfp =  max <$> pParens ((+1) <$> wfp) <*> wfp `opt` 0
 
 -- | It is very easy to recognise infix expressions with any number of priorities and operators:
 --
--- @ 
--- pOp (c, op) = op <$ pSym c
--- sepBy p op = pChainl op p
--- expr    = foldr sepBy factor [(pOp ('+', (+)) <|> pOp ('-', (-))),  pOp ('*' , (*))] 
--- factor  = pNatural <|> pParens expr
--- @
--- 
--- | which we can call:  @run expr \"15-3*5\"@
+-- > operators       = [[('+', (+)), ('-', (-))],  [('*' , (*))], [('^', (^))]]
+-- > same_prio  ops  = msum [ op <$ pSym c | (c, op) <- ops]
+-- > expr            = foldr pChainl ( pNatural <|> pParens expr) (map same_prio operators) -- 
 --
--- @
--- Result: 0
--- @
+-- which we can call:  
 --
--- | Note that also here correction takes place: @run expr \"2 + + 3 5\"@
+-- > run expr "15-3*5+2^5"
 --
--- @
--- Result: 37
--- Correcting steps: 
---     Deleted  ' ' at position 1 expecting one of ['0'..'9', '*', '-', '+']
---     Inserted '0' at position 3 expecting one of ['(', '0'..'9']
---     Deleted  ' ' at position 4 expecting one of ['(', '0'..'9']
---     Deleted  ' ' at position 6 expecting one of ['0'..'9', '*', '-', '+']
--- @
+-- > Result: 32
+--
+-- Note that also here correction takes place: 
+--
+-- > run expr "2 + + 3 5"
+--
+-- > Result: 37
+-- > Correcting steps: 
+-- >    Deleted  ' ' at position 1 expecting one of ['0'..'9', '^', '*', '-', '+']
+-- >    Deleted  ' ' at position 3 expecting one of ['(', '0'..'9']
+-- >    Inserted '0' at position 4 expecting '0'..'9'
+-- >    Deleted  ' ' at position 5 expecting one of ['(', '0'..'9']
+-- >    Deleted  ' ' at position 7 expecting one of ['0'..'9', '^', '*', '-', '+']
+-- 
 
 
 test11 = run expr "15-3*5"
+expr :: Parser Int
+operators       = [[('+', (+)), ('-', (-))],  [('*' , (*))], [('^', (^))]]
+same_prio  ops  = msum [ op <$ pSym c | (c, op) <- ops]
+expr            = foldr pChainl ( pNatural <|> pParens expr) (map same_prio operators) 
 
--- parsing expressions
-pOp (c, op) = op <$ pSym c
-expr    = foldr pChainl factor [(pOp ('+', (+)) <|> pOp ('-', (-))),  pOp ('*' , (*))] 
-factor  = pNatural <|> pParens expr
--- parsing numbers
-pDigit :: Parser Char
-pDigit = pSym ('0', '9')
-pDigitAsInt = digit2Int <$> pDigit 
-pNatural = foldl (\a b -> a * 10 + b ) 0 <$> pList1 pDigitAsInt
-digit2Int a =  ord a - ord '0'
 
--- | A common case where ambiguity arises is when we e.g. want to recognise identifiers, but only those which are not keywords. 
---   The combinator `micro` inserts steps with a specfied cost in the result of the parser which can be used to disambiguate:
+-- | A common case where ambiguity arises is when we e.g. want to recognise identifiers, 
+--   but only those which are not keywords. 
+--   The combinator `micro` inserts steps with a specfied cost in the result 
+--   of the parser which can be used to disambiguate:
 --
--- @
--- ident ::  Parser String
--- ident = ((:) <$> pSym ('a','z') <*> pMunch (\x -> 'a' <= x && x <= 'z') `micro` 2) <* spaces
--- idents = pList1 ident
--- pKey keyw = pToken keyw `micro` 1 <* spaces
--- spaces :: Parser String
--- spaces = pMunch (==' ')
--- takes_second_alt =   pList ident 
---                \<|> (\ c t e -> [\"IfThenElse\"] ++  c   ++  t  ++  e) 
---                    \<$ pKey \"if\"   \<*> pList_ng ident 
---                    \<* pKey \"then\" \<*> pList_ng ident
---                    \<* pKey \"else\" \<*> pList_ng ident  
--- @
+-- > 
+-- > ident ::  Parser String
+-- > ident = ((:) <$> pSym ('a','z') <*> pMunch (\x -> 'a' <= x && x <= 'z') `micro` 2) <* spaces
+-- > idents = pList1 ident
+-- > pKey keyw = pToken keyw `micro` 1 <* spaces
+-- > spaces :: Parser String
+-- > spaces = pMunch (==' ')
+-- > takes_second_alt =   pList ident 
+-- >                \<|> (\ c t e -> ["IfThenElse"] ++  c   ++  t  ++  e) 
+-- >                    \<$ pKey "if"   <*> pList_ng ident 
+-- >                    \<* pKey "then" <*> pList_ng ident
+-- >                    \<* pKey "else" <*> pList_ng ident  
 --
-
--- | A keyword is followed by a small cost @1@, which makes sure that identifiers which have a keyword as a prefix win over the keyword. Identifiers are however
+--  A keyword is followed by a small cost @1@, which makes sure that 
+--  identifiers which have a keyword as a prefix win over the keyword. Identifiers are however
 --   followed by a cost @2@, with as result that in this case the keyword wins. 
 --   Note that a limitation of this approach is that keywords are only recognised as such when expected!
 -- 
--- @
--- test13 = run takes_second_alt \"if a then if else c\"
--- test14 = run takes_second_alt \"ifx a then if else c\"
--- @
+-- > test13 = run takes_second_alt "if a then if else c"
+-- > test14 = run takes_second_alt "ifx a then if else c"
 -- 
--- with results:
+-- with results for @test13@ and @test14@:
 --
--- @
--- Text.ParserCombinators.UU.Examples> test14
--- Result: [\"IfThenElse\",\"a\",\"if\",\"c\"]
--- Text.ParserCombinators.UU.Examples> test14
--- Result: [\"ifx\",\"a\",\"then\",\"if\",\"else\",\"c\"]
--- @
+-- > Result: ["IfThenElse","a","if","c"]
+-- > Result: ["ifx","a","then","if", "else","c"]
+-- 
 
+-- | A mistake which is made quite often is to construct  a parser which can recognise a sequence of elements using one of the 
+--  derived combinators (say @`pList`@), but where the argument parser can recognise the empty string. 
+--  The derived combinators check whether this is the case and terminate the parsing process with an error message:
+--
+-- > run (pList spaces) ""
+-- > Result: *** Exception: The combinator pList
+-- >  requires that it's argument cannot recognise the empty string
+--
+-- > run (pMaybe spaces) " "
+-- > Result: *** Exception: The combinator pMaybe
+-- > requires that it's argument cannot recognise the empty string
 
-ident ::  Parser String
+
+test16 = run (pList spaces) "  "
+
 ident = ((:) <$> pSym ('a','z') <*> pMunch (\x -> 'a' <= x && x <= 'z') `micro` 2) <* spaces
 idents = pList1 ident
 
@@ -237,17 +253,49 @@
 test13 = run takes_second_alt "if a then if else c"
 test14 = run takes_second_alt "ifx a then if else c"
 
+-- | For documentation of @`pMerged`@ and @`<||>`@ see the module "Text.ParserCombinators.UU.Merge":
+--
+-- > run  (,,) `pMerged` (list_of pDigit <||> list_of pLower <||> list_of pUpper) "1AabCD2D3d"
+--
+-- results in
+-- 
+-- > Result: ("123","abd","ACDD")
+-- 
 
+test15 = run ((,,) `pMerged` (list_of pDigit <||> list_of pLower <||> list_of pUpper)) "1AabCD2D3d"
 
-munch = (,,) <$> pa <*> pMunch ( `elem` "^=*") <*> pb
+-- | The function
+--
+-- > munch =  pMunch ( `elem` "^=*") 
+--
+--  returns  the longest prefix of the input obeying the predicate:
+--
+-- > run munch "==^^**rest" 
+--
+-- > Result: "==^^**"
+-- > Correcting steps: 
+-- >    The token 'r' was not consumed by the parsing process.
+-- >    The token 'e' was not consumed by the parsing process.
+-- >    The token 's' was not consumed by the parsing process.
+-- >    The token 't' was not consumed by the parsing process.
+-- 
 
+munch :: Parser String
+munch =  pMunch ( `elem` "^=*") 
+
 -- bracketing expressions
-pParens :: Parser a -> Parser a
 pParens p =  pSym '(' *> p <* pSym ')'
 pBracks p =  pSym '[' *> p <* pSym ']'
 pCurlys p =  pSym '{' *> p <* pSym '}'
 
+-- parsing numbers
+
+pDigitAsInt = digit2Int <$> pDigit 
+pNatural = foldl (\a b -> a * 10 + b ) 0 <$> pList1 pDigitAsInt
+digit2Int a =  ord a - ord '0'
+
 -- parsing letters and identifiers
+pDigit = pSym ('0', '9')
 pLower  = pSym ('a','z')
 pUpper  = pSym ('A','Z')
 pLetter = pUpper <|> pLower
@@ -259,15 +307,11 @@
 pAnyToken = pAny pToken
 
 -- parsing two alternatives and returning both rsults
-pAscii = pSym ('\000', '\254')
-pIntList       ::Parser [Int] 
+pIntList :: Parser [Int]
 pIntList       =  pParens ((pSym ';') `pListSep` (read <$> pList (pSym ('0', '9'))))
-parseIntString :: Parser String
-parseIntString = pList (pAscii)
-
-parseBoth = pPair pIntList parseIntString
+parseIntString =  pList ( pSym ('\000', '\254'))
 
-pPair p q =  amb (Left <$> p <|> Right <$> q)
+parseBoth =  amb (Left <$> pIntList <|> Right <$> parseIntString)
 
 main :: IO ()
 main = do test1
diff --git a/src/Text/ParserCombinators/UU/Merge.hs b/src/Text/ParserCombinators/UU/Merge.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/ParserCombinators/UU/Merge.hs
@@ -0,0 +1,38 @@
+module Text.ParserCombinators.UU.Merge((<||>), pMerged, list_of) where
+
+import Text.ParserCombinators.UU.Core
+import Text.ParserCombinators.UU.Derived
+import Text.ParserCombinators.UU.BasicInstances
+
+-- | Often one wants to read a sequence of elements of different types, 
+--   where the actual order doe not matter. For the semantic processing however
+--   it would be nice to get the elemnts of each type collected together: 
+-- 
+-- >    chars_digs = cat3 `pMerged` (list_of pDig <||> list_of pL <||> list_of pU)
+-- 
+--  parsing \"12abCD1aV\" now returns \"121abaCDV\"; so the sequence of
+--  recognised elements is stored in three lists, which are then passed 
+--  to @cat3 :: [a] -> [a] -> [a] -> [a]@ which concatenates the lists again
+
+(<||>) ::  (c,     P st (d     -> d),     e -> f     -> g) 
+        -> (h,     P st (i     -> i),     g -> j     -> k) 
+        -> ((c,h), P st ((d,i) -> (d,i)), e -> (f,j) -> k)
+
+(pe, pp, punp) <||> (qe, qp, qunp)
+ =( (pe, qe)
+  , mapFst <$> pp <|>  mapSnd <$> qp
+  , \f (x, y) -> qunp (punp f x) y
+  )
+
+pMerged ::  c -> (d, P st (d -> d), c -> d -> e) -> P st e
+sem `pMerged` (units, alts, unp)
+ = let pres = alts <*> pres `opt` units in unp sem <$> pres
+
+list_of :: P st c -> ([d], P st ([c] -> [c]),e -> e)
+list_of p = ([], (:) <$> p, id)
+
+mapFst f (a, b) = (f a, b)
+mapSnd f (a, b) = (a, f b)
+
+
+
diff --git a/src/Text/ParserCombinators/UU/README.hs b/src/Text/ParserCombinators/UU/README.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/ParserCombinators/UU/README.hs
@@ -0,0 +1,22 @@
+-- | Tis module contains some background information about a completely new version of the Utrecht parser combinator library.
+--
+--   Background material
+--
+--   The library is based on ideas described in the paper:
+--
+--   \@inproceedings{uuparsing:piriapolis, Author = {Swierstra, S.~Doaitse},  Booktitle = {Language Engineering and Rigorous Software Development}, Editor = {Bove, A. and Barbosa, L. and Pardo, A. and and Sousa Pinto, J.}, Pages = {252-300}, Place = {Piriapolis},  Publisher = {Spinger}, Series = {LNCS}, Title = {Combinator Parsers: a short tutorial},  Volume = {5520}, Year = {2009}}
+--
+--   which is also available as a technical report from <http://www.cs.uu.nl/research/techreps/repo/CS-2008/2008-044.pdf>
+--
+--   The first part of this report is a general introduction into parser combinators, whereas the second part contains the 
+--   motivation for and documentation of the current package.
+--
+--   We appreciate if you include a reference to the above documentation in any publication describing software in which you have used the library succesfully.
+--
+--   Any feedback on particular use of the library, and suggestions for extensions, are welcome at mailto:doaitse\@swierstra.net
+--
+
+module Text.ParserCombinators.UU.README () where
+
+
+dummy = undefined
diff --git a/uu-parsinglib.cabal b/uu-parsinglib.cabal
--- a/uu-parsinglib.cabal
+++ b/uu-parsinglib.cabal
@@ -1,5 +1,5 @@
 Name:                uu-parsinglib
-Version:             2.4.0
+Version:             2.4.1
 Build-Type:          Simple
 License:             MIT
 Copyright:           S Doaitse Swierstra 
@@ -16,14 +16,14 @@
                      annotation free, applicative style parser combinators. In addition to this we even  provide a monadic interface.
                      Parsers do analyse themselves to avoid commonly made errors
                      .
-                     The file Text.ParserCombinators.UU.Examples contains a ready-made main function,
+                     The file "Text.ParserCombinators.UU.Examples" contains a ready-made main function,
                      which can be called to see the error correction at work. It contains extensive haddock documentation; 
                      try all the small tests for yourself to see the correction process at work, and to get a 
                      feeling for how to use the various combinators.
                      .
-                     The file CHANGELOG which is distributed with the pacakge describes the list of changes and additions
+                     The file "Text.ParserCombinators.UU.Changelog" contains a log of the most recent changes and additions
                      .
-                     The file README contains some references to background information
+                     The file "Text.ParserCombinators.UU.README" contains some references to background information
                      .
 Category:            Parsing
 
@@ -32,8 +32,12 @@
 
   Build-Depends:     base >= 4 && <5, haskell98
   Exposed-modules:   Text.ParserCombinators.UU
+                     Text.ParserCombinators.UU.CHANGELOG
+                     Text.ParserCombinators.UU.README
                      Text.ParserCombinators.UU.Core  
                      Text.ParserCombinators.UU.BasicInstances
-                     Text.ParserCombinators.UU.Derived 
+                     Text.ParserCombinators.UU.Derived
+                     Text.ParserCombinators.UU.Merge 
                      Text.ParserCombinators.UU.Examples
                      Text.ParserCombinators.UU.Parsing
+
