diff --git a/COPYRIGHT b/COPYRIGHT
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -6,7 +6,7 @@
     (c) copyright 1998-2000    Malcolm Wallace
 The modules Text.ParserCombinators.Poly* and Text.Parse and Text.Parse.*
 are
-    (c) copyright 2006-2010    Malcolm Wallace
+    (c) copyright 2006-2011    Malcolm Wallace
 
 These modules are licensed under the terms of the GNU Lesser
 General Public Licence (LGPL), which can be found in the file called
diff --git a/polyparse.cabal b/polyparse.cabal
--- a/polyparse.cabal
+++ b/polyparse.cabal
@@ -1,5 +1,5 @@
 name:		polyparse
-version:	1.5
+version:	1.6
 license:	LGPL
 license-file:	COPYRIGHT
 author:		Malcolm Wallace <Malcolm.Wallace@me.com>
@@ -36,12 +36,13 @@
         Text.Parse
   if impl(ghc)
     build-depends:	bytestring
---  build-depends:	 text
+    build-depends:	 text
     exposed-modules:
-        Text.ParserCombinators.Poly.ByteString,
+        Text.ParserCombinators.Poly.ByteString
         Text.Parse.ByteString
---      Text.ParserCombinators.Poly.Text,
+        Text.ParserCombinators.Poly.Text
+        Text.ParserCombinators.Poly.StateText
 --      Text.Parse.Text
-  cpp-options:		-DVERSION="1.5"
+  cpp-options:		-DVERSION="1.6"
   nhc98-options:	-K6M
   extensions:		CPP
diff --git a/src/Text/ParserCombinators/Poly/Base.hs b/src/Text/ParserCombinators/Poly/Base.hs
--- a/src/Text/ParserCombinators/Poly/Base.hs
+++ b/src/Text/ParserCombinators/Poly/Base.hs
@@ -13,13 +13,10 @@
   , indent	-- :: Int -> String -> String
     -- ** Choices
   , oneOf	-- :: PolyParse p => [p a] -> p a
-  , optional	-- :: PolyParse p => p a -> p (Maybe a)
     -- ** Sequences
   , exactly	-- :: PolyParse p => Int -> p a -> p [a]
   , upto	-- :: PolyParse p => Int -> p a -> p [a]
-  , many	-- :: PolyParse p => p a -> p [a]
   , many1	-- :: PolyParse p => p a -> p [a]
-  , some	-- :: PolyParse p => p a -> p [a]
   , sepBy	-- :: PolyParse p => p a -> p sep -> p [a]
   , sepBy1	-- :: PolyParse p => p a -> p sep -> p [a]
   , bracketSep	-- :: PolyParse p => p bra -> p sep -> p ket -> p a -> p [a]
diff --git a/src/Text/ParserCombinators/Poly/StateText.hs b/src/Text/ParserCombinators/Poly/StateText.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/ParserCombinators/Poly/StateText.hs
@@ -0,0 +1,159 @@
+module Text.ParserCombinators.Poly.StateText
+  ( -- * The Parser datatype
+    Parser(P)
+  , Result(..)
+  , runParser
+    -- ** Basic parsers
+  , next
+  , eof
+  , satisfy
+  , onFail
+    -- ** Derived parsers (but implemented more efficiently)
+  , manySatisfy
+  , many1Satisfy
+    -- ** State-handling
+  , stUpdate    -- :: (s->s) -> Parser s t ()
+  , stQuery     -- :: (s->a) -> Parser s t a
+  , stGet       -- :: Parser s t s
+    -- ** Re-parsing
+  , reparse
+    -- * Re-export all more general combinators
+  , module Text.ParserCombinators.Poly.Base
+  , module Control.Applicative
+  ) where
+
+
+import Text.ParserCombinators.Poly.Base
+import Text.ParserCombinators.Poly.Result
+import qualified Data.Text.Lazy as T
+import Data.Text.Lazy (Text)
+import Control.Applicative
+
+-- | This @Parser@ datatype is a specialised parsing monad with error
+--   reporting.  Whereas the standard version can be used for arbitrary
+--   token types, this version is specialised to Text input only.
+newtype Parser s a = P (s -> Text -> Result (Text,s) a)
+
+-- | Apply a parser to an input token sequence.
+runParser :: Parser s a -> s -> Text -> (Either String a, s, Text)
+runParser (P p) = \s -> reTuple . resultToEither . p s
+  where
+    reTuple (either, (z,s)) = (either, s, z)
+
+instance Functor (Parser s) where
+    fmap f (P p) = P (\s-> fmap f . p s)
+
+instance Monad (Parser s) where
+    return x     = P (\s ts-> Success (ts,s) x)
+    fail e       = P (\s ts-> Failure (ts,s) e)
+    (P f) >>= g  = P (\s-> continue . f s)
+      where
+        continue (Success (ts,s) x)         = let (P g') = g x in g' s ts
+        continue (Committed (Committed r))  = continue (Committed r)
+        continue (Committed r)              = Committed (continue r)
+        continue (Failure ts e)             = Failure ts e
+
+instance Commitment (Parser s) where
+    commit (P p)         = P (\s-> Committed . p s)
+    (P p) `adjustErr` f  = P (\s-> adjust . p s)
+      where
+        adjust (Failure z e) = Failure z (f e)
+        adjust (Committed r) = Committed (adjust r)
+        adjust  good         = good
+
+    oneOf' = accum []
+      where accum errs [] =
+                fail ("failed to parse any of the possible choices:\n"
+                            ++indent 2 (concatMap showErr (reverse errs)))
+            accum errs ((e,P p):ps) =
+                P (\s ts-> case p s ts of
+                           Failure _ err ->
+                                       let (P p') = accum ((e,err):errs) ps
+                                       in p' s ts
+                           r@(Success _ _)    -> r
+                           r@(Committed _)    -> r )
+            showErr (name,err) = name++":\n"++indent 2 err
+
+instance Applicative (Parser s) where
+    pure f    = return f
+    pf <*> px = do { f <- pf; x <- px; return (f x) }
+#if defined(GLASGOW_HASKELL) && GLASGOW_HASKELL > 610
+    p  <*  q  = p `discard` q
+#endif
+
+instance Alternative (Parser s) where
+    empty     = fail "no parse"
+    p <|> q   = p `onFail` q
+
+instance PolyParse (Parser s)
+
+------------------------------------------------------------------------
+
+-- | Simply return the next token in the input tokenstream.
+next :: Parser s Char
+next = P (\s bs-> case T.uncons bs of
+                  Nothing       -> Failure (bs,s) "Ran out of input (EOF)"
+                  Just (c, bs') -> Success (bs',s) c )
+
+-- | Succeed if the end of file/input has been reached, fail otherwise.
+eof :: Parser s ()
+eof = P (\s bs -> if T.null bs
+                  then Success (bs,s) ()
+                  else Failure (bs,s) "Expected end of input (EOF)" )
+
+-- | Return the next token if it satisfies the given predicate.
+satisfy :: (Char -> Bool) -> Parser s Char
+satisfy f = do { x <- next
+               ; if f x then return x else fail "Parse.satisfy: failed"
+               }
+
+-- | @p `onFail` q@ means parse p, unless p fails, in which case
+--   parse q instead.
+--   Can be chained together to give multiple attempts to parse something.
+--   (Note that q could itself be a failing parser, e.g. to change the error
+--   message from that defined in p to something different.)
+--   However, a severe failure in p cannot be ignored.
+onFail :: Parser s a -> Parser s a -> Parser s a
+(P p) `onFail` (P q) = P (\s ts-> continue s ts $ p s ts)
+  where continue s ts (Failure _ _) = q s ts
+    --  continue _ _  (Committed r) = r	-- no, remain Committed
+        continue _ _  r             = r
+
+------------------------------------------------------------------------
+
+-- | @manySatisfy p@ is a more efficient fused version of @many (satisfy p)@
+manySatisfy :: (Char->Bool) -> Parser s Text
+manySatisfy f = P (\s bs-> let (pre,suf) = T.span f bs in Success (suf,s) pre)
+
+-- | @many1Satisfy p@ is a more efficient fused version of @many1 (satisfy p)@
+many1Satisfy :: (Char->Bool) -> Parser s Text
+many1Satisfy f = do x <- manySatisfy f
+                    if T.null x then fail "Parse.many1Satisfy: failed"
+                                else return x
+
+------------------------------------------------------------------------
+-- State handling
+
+-- | Update the internal state.
+stUpdate   :: (s->s) -> Parser s ()
+stUpdate f  = P (\s bs-> Success (bs, f s) ())
+
+-- | Query the internal state.
+stQuery    :: (s->a) -> Parser s a
+stQuery f   = P (\s bs-> Success (bs,s) (f s))
+
+-- | Deliver the entire internal state.
+stGet      :: Parser s s
+stGet       = P (\s bs-> Success (bs,s) s)
+
+------------------------------------------------------------------------
+
+-- | Push some tokens back onto the front of the input stream and reparse.
+--   This is useful e.g. for recursively expanding macros.  When the
+--   user-parser recognises a macro use, it can lookup the macro
+--   expansion from the parse state, lex it, and then stuff the
+--   lexed expansion back down into the parser.
+reparse    :: Text -> Parser s ()
+reparse ts  = P (\s inp-> Success (ts `T.append` inp,s) ())
+
+------------------------------------------------------------------------
diff --git a/src/Text/ParserCombinators/Poly/Text.hs b/src/Text/ParserCombinators/Poly/Text.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/ParserCombinators/Poly/Text.hs
@@ -0,0 +1,138 @@
+module Text.ParserCombinators.Poly.Text
+  ( -- * The Parser datatype
+    Parser(P)
+  , Result(..)
+  , runParser
+    -- ** Basic parsers
+  , next
+  , eof
+  , satisfy
+  , onFail
+    -- ** Derived parsers (but implemented more efficiently)
+  , manySatisfy
+  , many1Satisfy
+    -- ** Re-parsing
+  , reparse
+    -- * Re-export all more general combinators
+  , module Text.ParserCombinators.Poly.Base
+  , module Control.Applicative
+  ) where
+
+
+import Text.ParserCombinators.Poly.Base
+import Text.ParserCombinators.Poly.Result
+import qualified Data.Text.Lazy as T
+import Data.Text.Lazy (Text)
+import Control.Applicative
+
+-- | This @Parser@ datatype is a specialised parsing monad with error
+--   reporting.  Whereas the standard version can be used for arbitrary
+--   token types, this version is specialised to Text input only.
+newtype Parser a = P (Text -> Result Text a)
+
+-- | Apply a parser to an input token sequence.
+runParser :: Parser a -> Text -> (Either String a, Text)
+runParser (P p) = resultToEither . p
+
+instance Functor Parser where
+    fmap f (P p) = P (fmap f . p)
+
+instance Monad Parser where
+    return x     = P (\ts-> Success ts x)
+    fail e       = P (\ts-> Failure ts e)
+    (P f) >>= g  = P (continue . f)
+      where
+        continue (Success ts x)             = let (P g') = g x in g' ts
+        continue (Committed (Committed r))  = continue (Committed r)
+        continue (Committed r)              = Committed (continue r)
+        continue (Failure ts e)             = Failure ts e
+
+instance Commitment Parser where
+    commit (P p)         = P (Committed . p)
+    (P p) `adjustErr` f  = P (adjust . p)
+      where
+        adjust (Failure z e) = Failure z (f e)
+        adjust (Committed r) = Committed (adjust r)
+        adjust  good         = good
+
+    oneOf' = accum []
+      where accum errs [] =
+                fail ("failed to parse any of the possible choices:\n"
+                            ++indent 2 (concatMap showErr (reverse errs)))
+            accum errs ((e,P p):ps) =
+                P (\ts-> case p ts of
+                           Failure _ err ->
+                                       let (P p') = accum ((e,err):errs) ps
+                                       in p' ts
+                           r@(Success _ _)    -> r
+                           r@(Committed _)    -> r )
+            showErr (name,err) = name++":\n"++indent 2 err
+
+instance Applicative Parser where
+    pure f    = return f
+    pf <*> px = do { f <- pf; x <- px; return (f x) }
+#if defined(GLASGOW_HASKELL) && GLASGOW_HASKELL > 610
+    p  <*  q  = p `discard` q
+#endif
+
+instance Alternative Parser where
+    empty     = fail "no parse"
+    p <|> q   = p `onFail` q
+
+instance PolyParse Parser
+
+------------------------------------------------------------------------
+
+-- | Simply return the next token in the input tokenstream.
+next :: Parser Char
+next = P (\bs-> case T.uncons bs of
+                Nothing       -> Failure bs "Ran out of input (EOF)"
+                Just (c, bs') -> Success bs' c )
+
+-- | Succeed if the end of file/input has been reached, fail otherwise.
+eof :: Parser ()
+eof = P (\bs -> if T.null bs
+                then Success bs ()
+                else Failure bs "Expected end of input (EOF)" )
+
+-- | Return the next token if it satisfies the given predicate.
+satisfy :: (Char -> Bool) -> Parser Char
+satisfy f = do { x <- next
+               ; if f x then return x else fail "Parse.satisfy: failed"
+               }
+
+-- | @p `onFail` q@ means parse p, unless p fails, in which case
+--   parse q instead.
+--   Can be chained together to give multiple attempts to parse something.
+--   (Note that q could itself be a failing parser, e.g. to change the error
+--   message from that defined in p to something different.)
+--   However, a severe failure in p cannot be ignored.
+onFail :: Parser a -> Parser a -> Parser a
+(P p) `onFail` (P q) = P (\ts-> continue ts $ p ts)
+  where continue ts (Failure _ _) = q ts
+    --  continue _  (Committed r) = r	-- no, remain Committed
+        continue _  r             = r
+
+------------------------------------------------------------------------
+
+-- | @manySatisfy p@ is a more efficient fused version of @many (satisfy p)@
+manySatisfy :: (Char->Bool) -> Parser Text
+manySatisfy f = P (\bs-> let (pre,suf) = T.span f bs in Success suf pre)
+
+-- | @many1Satisfy p@ is a more efficient fused version of @many1 (satisfy p)@
+many1Satisfy :: (Char->Bool) -> Parser Text
+many1Satisfy f = do x <- manySatisfy f
+                    if T.null x then fail "Parse.many1Satisfy: failed"
+                                else return x
+
+------------------------------------------------------------------------
+
+-- | Push some tokens back onto the front of the input stream and reparse.
+--   This is useful e.g. for recursively expanding macros.  When the
+--   user-parser recognises a macro use, it can lookup the macro
+--   expansion from the parse state, lex it, and then stuff the
+--   lexed expansion back down into the parser.
+reparse    :: Text -> Parser ()
+reparse ts  = P (\inp-> Success (ts `T.append` inp) ())
+
+------------------------------------------------------------------------
