diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.1 (2024-05-27)
+* add `TakeRest` combinator
+* re-add `:<|>:` combinator with more accurate behaviour clarification
+
 ## 1.0.0 (2024-05-25)
 * small rewrite, changing how `Done` works (now non-consuming)
 * single all parsers
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,80 +1,72 @@
 # Symparsec
-Type level string (`Symbol`) parser combinators. Reify to runtime parsers with
-guaranteed identical behaviour.
+[hackage-parsec]: https://hackage.haskell.org/package/parsec
 
-It's a Parsec-like for `Symbol`s; thus, Symparsec.
+Type level string (`Symbol`) parser combinators. A [Parsec][hackage-parsec]-like
+for `Symbol`s; thus, Symparsec! With all the features you'd expect:
 
-Previously named symbol-parser.
+* define parsers compositionally, largely as you would on the term level
+* pretty, detailed parse errors
+* decent performance (for simple parsers)
 
-Requires GHC 9.6 for singling parsers.
+Parsers may also be reified and used at runtime with _guaranteed identical
+behaviour_ via a healthy dose of singletons.
 
-## Features
-* Define parsers compositionally, largely as you would on the term level.
-* Pretty parse errors.
-* Hopefully decent performance.
-* Reify parsers to term level with guaranteed identical behaviour via a
-  healthy dose of singletons.
+Requires GHC >= 9.6.
 
 ## Examples
+Define a type-level parser:
+
 ```haskell
-ghci> import Symparsec
-ghci> :k! Run (Drop 3 :*>: Isolate 2 NatDec :<*>: (Drop 3 :*>: NatHex)) "___10___FF"
-...
-= Right '( '(10, 255), "")
+import Symparsec
+type PExample = Skip 1 :*>: Isolate 2 NatHex :<*>: (Literal "_" :*>: TakeRest)
 ```
 
+Use it to parse a type-level string (in a GHCi session):
+
+```haskell
+ghci> :k! Run PExample "xFF_"
+Run ...
+= Right '( '(255, "etc"), "")
+```
+
+Use it to parse a different, term-level string:
+
+```haskell
+ghci> import Singleraeh.Demote ( demote )
+ghci> run' @PExample demote "abc_123"
+Right ((188,"123"),"")
+```
+
 ## Why?
 Via `GHC.Generics`, we may inspect Haskell data types on the type level.
 Constructor names are `Symbols`. Ever reify these, then perform some sort of
 checking or parsing on the term level? Symparsec does the parsing on the type
 level instead. Catch bugs earlier, get faster runtime.
 
+Also type-level Haskell authors deserve fun libraries too!!
+
 ## Design
 ### The parser
-A parser is a 4-tuple of:
+A parser is a 3-tuple of:
 
-* a consuming character parser; given a character and a state, returns
+* a character parser; given a character and a state, returns
   * `Cont s`: keep going, here's the next state `s`
-  * `Done r`: parse successful with value `r`
+  * `Done r`: parse successful with value `r`, _do not consume character_
   * `Err  E`: parse error, details in the `E` (a structured error)
 * an end handler, which takes only a state, and can only return `Done` or `Err`
-* an initial "raw" state
-* a state initializer, which turns the initial "raw" state into the first state
-  value (the indirection here assists singling)
+* an initial state
 
-Running a parser is simple:
+Running such a parser is very simple:
 
 * initialize state
 * parse character by character until end of input, or `Done`/`Err`
 
 Parsers may not communicate with the runner any other way. This means no
 backtracking, chunking etc. This is a conscious decision, made for simplicity.
-
-Note that due to character parsers being consuming, we often need to do a bit of
-"internal lookahead", where we check if we expect to consume any more
-characters, and if not then emit a `Done`. It also means that non-consuming
-parsers such as `Take 0` are invalid for non-empty strings. The state
-initializer should be used to catch such cases.
-
-This is a rough overview of parser design. See the code and/or Haddock
-documentation for precise details.
-
-### Pitfall: Character parsers always consume
-There is no backtracking or lookahead, that you do not implement yourself. This
-keeps the parser execution extremely simple, but breaks null parsers such as
-`Drop 0`, so these must be handled specially (unless you don't getting mind
-stuck type families on misuse).
-
-For concrete examples, see the implementation of `Drop` and `Literal`.
-
-### Pitfall: Not all parsers are definable
-* No changing parser state. Thus, parsers such as `Try :: Parser s r -> Parser
-  (s, [Char]) r` are not definable. _Parsers may not backtrack._
-  * Combinators such as `<|>` can emulate backtracking, but they are complex and
-    hard to reason about (they may have bugs!).
+We're still able to implement a good handful of parser combinators regardless,
+including a limited form of backtracking.
 
-### Feature: Parsers may be reified to use at runtime, with guaranteed same behaviour
-TODO
+This is a rough overview. See the code & Haddocks for precise details.
 
 ## Contributing
 I would gladly accept further combinators or other suggestions. Please add an
diff --git a/src/Symparsec/Internal/List.hs b/src/Symparsec/Internal/List.hs
deleted file mode 100644
--- a/src/Symparsec/Internal/List.hs
+++ /dev/null
@@ -1,9 +0,0 @@
-{-# LANGUAGE UndecidableInstances #-}
-
-module Symparsec.Internal.List where
-
--- | Reverse a type level list.
-type Reverse as = Reverse' as '[]
-type family Reverse' (as :: [k]) (acc :: [k]) :: [k] where
-  Reverse' '[]      acc = acc
-  Reverse' (a : as) acc = Reverse' as (a : acc)
diff --git a/src/Symparsec/Parser.hs b/src/Symparsec/Parser.hs
--- a/src/Symparsec/Parser.hs
+++ b/src/Symparsec/Parser.hs
@@ -77,11 +77,6 @@
         -> SParser ss sr ('PParser pCh pEnd s0)
 
 -- | Parse a 'Char' with the given state.
---
--- The action is always consuming. For this reason, you may need to look ahead
--- for the final case, so as to not consume an extra 'Char'. This prevents many
--- zero-length parsers. It's a bit weird. See
--- 'Data.Type.Symbol.Parser.Parser.Drop' for an example.
 type  ParserCh str s r = Char -> s -> Result str s r
 type PParserCh     s r = ParserCh Symbol s r
 
diff --git a/src/Symparsec/Parser/Common.hs b/src/Symparsec/Parser/Common.hs
--- a/src/Symparsec/Parser/Common.hs
+++ b/src/Symparsec/Parser/Common.hs
@@ -20,13 +20,15 @@
 import Singleraeh.Either
 
 -- | Fail with the given message when given any character to parse.
+type FailCh name e = Err (EBase name e)
+
 type FailChSym :: Symbol -> PDoc -> ParserChSym s r
 data FailChSym name e f
 type instance App (FailChSym name e) f = FailChSym1 name e f
 
 type FailChSym1 :: Symbol -> PDoc -> ParserChSym1 s r
 data FailChSym1 name e ch s
-type instance App (FailChSym1 name e ch) s = Err (EBase name e)
+type instance App (FailChSym1 name e ch) s = FailCh name e
 
 failChSym
     :: SSymbol name -> SDoc e -> SParserChSym ss sr (FailChSym name e)
diff --git a/src/Symparsec/Parser/End.hs b/src/Symparsec/Parser/End.hs
--- a/src/Symparsec/Parser/End.hs
+++ b/src/Symparsec/Parser/End.hs
@@ -1,24 +1,32 @@
 module Symparsec.Parser.End where
 
 import Symparsec.Parser.Common
-import DeFun.Core ( Con1, con1 )
+import DeFun.Core
 import Singleraeh.Tuple ( SUnit(..) )
 import Singleraeh.Either ( SEither(..) )
-import GHC.TypeLits ( symbolSing )
-import TypeLevelShow.Doc ( singDoc )
 
 -- | Assert end of symbol, or fail.
 type End :: PParser () ()
-type End = 'PParser
-    (FailChSym "End" (Text "expected end of string"))
-    (Con1 Right)
-    '()
+type End = 'PParser EndChSym (Con1 Right) '()
 
 sEnd :: SParser SUnit SUnit End
-sEnd = SParser (failChSym symbolSing singDoc) (con1 SRight) SUnit
+sEnd = SParser sEndChSym (con1 SRight) SUnit
 
--- TODO orphan instance. if I need to, make some dumb type family idk.
 instance SingParser End where
     type PS  End = SUnit
     type PR  End = SUnit
     singParser' = sEnd
+
+-- it'd be nice to just reuse FailChSym here but we get told off for writing an
+-- orphan instance. fair enough, write this instead
+type EndChSym :: ParserChSym s r
+data EndChSym f
+type instance App EndChSym f = EndChSym1 f
+
+type EndChSym1 :: ParserChSym1 s r
+data EndChSym1 ch s
+type instance App (EndChSym1 ch) s =
+    Err (EBase "End" (Text "expected end of string"))
+
+sEndChSym :: SParserChSym ss rr EndChSym
+sEndChSym = Lam2 $ \_ch _s -> SErr singE
diff --git a/src/Symparsec/Parser/Or.hs b/src/Symparsec/Parser/Or.hs
new file mode 100644
--- /dev/null
+++ b/src/Symparsec/Parser/Or.hs
@@ -0,0 +1,330 @@
+{-# LANGUAGE UndecidableInstances #-}
+
+module Symparsec.Parser.Or where
+
+import Symparsec.Parser
+import TypeLevelShow.Doc
+import GHC.TypeLits hiding ( ErrorMessage(..) )
+import DeFun.Core
+import Singleraeh.Tuple
+import Singleraeh.Either
+import Singleraeh.List
+
+{- | Limited parser choice. Try left; if it fails, backtrack and try right.
+     However, _the right choice must consume at least as much as the left
+     choice._ If it doesn't, then even if the right parser succeeds, it
+     will emit an error.
+
+This behaviour is due to the parser runner not supporting backtracking. We can
+emulate it by storing a record of the characters parsed so far, and "replaying"
+these on the right parser if the left parser fails. If the right parser ends
+before we finish replaying, we will have consumed extra characters that we can't
+ask the runner to revert.
+
+For example, @Literal "abcd" :<|>: Literal "ab"@ is bad. An input of @abcX@ will
+trigger the consumption error.
+
+I can't think of another way to implement this with the current parser design. I
+think it's the best we have. A more complex parser design may permit changing
+internal running state, so we could save and load state (this would permit a
+@Try p@ parser). But that's scary. And you're better off designing your
+type-level string schemas to permit non-backtracking parsing anyway...
+
+Also problematic is that we never emit a left parser error, so errors can
+degrade. Perhaps your string was one character off a successful left parse; but
+if it fails, you won't see that error.
+-}
+infixl 3 :<|>:
+type (:<|>:)
+    :: PParser sl rl
+    -> PParser sr rr
+    -> PParser (OrS sl sr) (Either rl rr)
+type family pl :<|>: pr where
+    'PParser plCh plEnd s0l :<|>: 'PParser prCh prEnd s0r =
+        Or' plCh plEnd s0l prCh prEnd s0r
+
+type Or' plCh plEnd s0l prCh prEnd s0r = 'PParser
+    (OrChSym plCh prCh s0r)
+    (OrEndSym plEnd prCh prEnd s0r)
+    (Left '(s0l, '[]))
+
+type SOrS ssl ssr = SEither (STuple2 ssl (SList SChar)) ssr
+type OrS  sl  sr  = Either (sl, [Char]) sr
+type SPOr ssl srl ssr srr plCh plEnd s0l prCh prEnd s0r =
+    SParser (SOrS ssl ssr) (SEither srl srr) (Or' plCh plEnd s0l prCh prEnd s0r)
+
+sOr
+    :: SParser ssl srl ('PParser plCh plEnd s0l)
+    -> SParser ssr srr ('PParser prCh prEnd s0r)
+    -> SPOr    ssl srl ssr srr plCh plEnd s0l prCh prEnd s0r
+sOr (SParser plCh plEnd s0l) (SParser prCh prEnd s0r) = SParser
+    (sOrChSym plCh prCh s0r)
+    (sOrEndSym plEnd prCh prEnd s0r)
+    (SLeft (STuple2 s0l SNil))
+
+instance
+  ( pl ~ 'PParser plCh plEnd s0l
+  , pr ~ 'PParser prCh prEnd s0r
+  , SingParser pl
+  , SingParser pr
+  ) => SingParser (Or' plCh plEnd s0l prCh prEnd s0r) where
+    type PS (Or' plCh plEnd s0l prCh prEnd s0r) = SOrS
+        (PS ('PParser plCh plEnd s0l))
+        (PS ('PParser prCh prEnd s0r))
+    type PR (Or' plCh plEnd s0l prCh prEnd s0r) = SEither
+        (PR ('PParser plCh plEnd s0l))
+        (PR ('PParser prCh prEnd s0r))
+    singParser' = sOr (singParser @pl) (singParser @pr)
+
+type OrCh
+    :: ParserChSym sl rl
+    -> ParserChSym sr rr
+    -> sr
+    -> PParserCh (OrS sl sr) (Either rl rr)
+type family OrCh plCh prCh sr ch s where
+    -- | parsing left
+    OrCh plCh prCh s0r ch (Left  '(sl, chs)) =
+        OrChL prCh s0r ch chs (plCh @@ ch @@ sl)
+
+    -- | parsing right (after left failed and was successfully replayed)
+    OrCh plCh prCh _  ch (Right sr) =
+        OrChR (prCh @@ ch @@ sr)
+
+type OrChL
+    :: ParserChSym sr rr
+    -> sr
+    -> Char
+    -> [Char]
+    -> PResult sl rl
+    -> PResult (Either (sl, [Char]) sr) (Either rl rr)
+type family OrChL prCh s0r chLast chs resl where
+    -- | left parser OK, continue
+    OrChL _    _   chLast chs (Cont sl) = Cont (Left  '(sl, chLast : chs))
+
+    -- | left parser OK, done
+    OrChL _    _   _      _   (Done rl) = Done (Left  rl)
+
+    -- | left parser failed: ignore, replay consumed characters on right parser
+    OrChL prCh s0r chLast chs (Err  _ ) =
+        OrChLReplay prCh chLast (Reverse chs) (Cont s0r)
+
+type OrChLReplay
+    :: ParserChSym sr rr
+    -> Char
+    -> [Char]
+    -> PResult sr rr
+    -> PResult (Either (sl, [Char]) sr) (Either rl rr)
+type family OrChLReplay prCh chLast chs resr where
+    -- | right parser OK, keep replaying
+    OrChLReplay prCh chLast (ch : chs) (Cont sr) =
+        OrChLReplay prCh chLast chs (prCh @@ ch @@ sr)
+    --
+    -- | right parser OK, final replay char
+    OrChLReplay prCh chLast '[]        (Cont sr) = OrChR (prCh @@ chLast @@ sr)
+
+    -- | right parser fail: wrap error
+    OrChLReplay prCh chLast chs        (Err  er) = Err (EOrR er)
+
+    -- | right parser done but still replaying! no choice but to error out
+    OrChLReplay prCh chLast chs        (Done rr) = Err EOrStillReplaying
+        -- Done (Right rr) -- TODO
+
+sOrChLReplay
+    :: SParserChSym ssr srr prCh
+    -> SChar chLast
+    -> SList SChar chs
+    -> SResult ssr srr resr
+    -> SResult (SOrS ssl ssr) (SEither srl srr)
+        (OrChLReplay prCh chLast chs resr)
+sOrChLReplay prCh chLast chs resr =
+    case chs of
+      SCons ch chs' ->
+        case resr of
+          SCont  sr ->
+            sOrChLReplay prCh chLast chs' (prCh @@ ch @@ sr)
+          SDone _rr -> SErr eOrStillReplaying
+          SErr   er -> SErr $ eOrR er
+      SNil ->
+        case resr of
+          SCont  sr -> sOrChR (prCh @@ chLast @@ sr)
+          SDone _rr -> SErr eOrStillReplaying
+          SErr   er -> SErr $ eOrR er
+
+type EOrR er = EIn "Or(R)" er
+eOrR :: SE er -> SE (EOrR er)
+eOrR er = SEIn symbolSing er
+
+type EOrStillReplaying = EBase "Or"
+    (Text "right parser much consume at least as much as the failed left parser")
+eOrStillReplaying :: SE EOrStillReplaying
+eOrStillReplaying = singE
+
+type family OrChR resr where
+    OrChR (Cont sr) = Cont (Right sr)
+    OrChR (Done rr) = Done (Right rr)
+    OrChR (Err  er) = Err (EOrR er)
+
+sOrChR
+    :: SResult ssr srr resr
+    -> SResult (SOrS ssl ssr) (SEither srl srr) (OrChR resr)
+sOrChR = \case
+  SCont sr -> SCont $ SRight sr
+  SDone rr -> SDone $ SRight rr
+  SErr  er -> SErr  $ eOrR er
+
+type OrEnd
+    :: ParserEndSym sl rl
+    -> ParserChSym  sr rr
+    -> ParserEndSym sr rr
+    -> sr
+    -> PParserEnd (Either (sl, [Char]) sr) (Either rl rr)
+type family OrEnd plEnd prCh prEnd sr res where
+    -- | input ended during left parser
+    OrEnd plEnd prCh prEnd s0r (Left  '(sl, chs)) =
+        OrEndL prCh prEnd s0r chs (plEnd @@ sl)
+
+    -- | input ended during right parser: call right end
+    OrEnd plEnd prCh prEnd _   (Right sr)         = OrEndR (prEnd @@ sr)
+
+type OrEndR :: PResultEnd rr -> PResultEnd (Either rl rr)
+type family OrEndR resr where
+    OrEndR (Right rr) = Right (Right rr)
+    OrEndR (Left  er) = Left  (EOrR er)
+
+sOrEndR
+    :: SResultEnd srr resr
+    -> SResultEnd (SEither srl srr) (OrEndR resr)
+sOrEndR = \case
+  SRight rr -> SRight $ SRight rr
+  SLeft  er -> SLeft  $ eOrR er
+
+type OrEndL
+    :: ParserChSym  sr rr
+    -> ParserEndSym sr rr
+    -> sr
+    -> [Char]
+    -> Either PE rl
+    -> Either PE (Either rl rr)
+type family OrEndL prCh prEnd s0r chs resl where
+    -- | input ended during left parser and left end succeeeded: phew
+    OrEndL prCh prEnd s0r chs (Right rl) = Right (Left rl)
+
+    -- | input ended during left parser and left end failed. replay on right,
+    --   then eventually call right end
+    OrEndL prCh prEnd s0r chs (Left  el) =
+        OrEndLReplay prCh prEnd (Reverse chs) (Cont s0r)
+
+sOrEndL
+    :: SParserChSym  ssr srr prCh
+    -> SParserEndSym ssr srr prEnd
+    -> ssr s0r
+    -> SList SChar chs
+    -> SResultEnd srl resl
+    -> SResultEnd (SEither srl srr) (OrEndL prCh prEnd s0r chs resl)
+sOrEndL prCh prEnd s0r chs = \case
+  SRight  rl -> SRight $ SLeft rl
+  SLeft  _el -> sOrEndLReplay prCh prEnd (sReverse chs) (SCont s0r)
+
+type OrEndLReplay
+    :: ParserChSym  sr rr
+    -> ParserEndSym sr rr
+    -> [Char]
+    -> PResult sr rr
+    -> Either PE (Either rl rr)
+type family OrEndLReplay prCh prEnd chs resr where
+    -- | right parser OK, keep replaying
+    OrEndLReplay prCh prEnd (ch : chs) (Cont sr) =
+        OrEndLReplay prCh prEnd chs (prCh @@ ch @@ sr)
+
+    -- | replay complete
+    OrEndLReplay prCh prEnd '[]        resr      = OrEndLReplay' prEnd resr
+
+    -- | right parser fail: wrap error
+    OrEndLReplay prCh prEnd chs        (Err  er) = Left (EOrR er)
+
+    -- | right parser done but still replaying! no choice but to error out
+    OrEndLReplay prCh prEnd chs        (Done rr) = Left EOrStillReplaying
+        -- Right (Right rr) TODO
+
+sOrEndLReplay
+    :: SParserChSym  ssr srr prCh
+    -> SParserEndSym ssr srr prEnd
+    -> SList SChar chs
+    -> SResult ssr srr resr
+    -> SResultEnd (SEither srl srr) (OrEndLReplay prCh prEnd chs resr)
+sOrEndLReplay prCh prEnd chs resr =
+    case chs of
+      SCons ch chs' ->
+        case resr of
+          SCont  sr ->
+            sOrEndLReplay prCh prEnd chs' (prCh @@ ch @@ sr)
+          SErr   er -> SLeft $ eOrR er
+          SDone _rr -> SLeft eOrStillReplaying
+      SNil ->
+        case resr of
+          SCont sr -> sOrEndR $ prEnd @@ sr
+          SDone rr -> SRight  $ SRight rr
+          SErr  er -> SLeft   $ eOrR er
+
+type family OrEndLReplay' prEnd resr where
+    OrEndLReplay' prEnd (Cont sr) = OrEndR (prEnd @@ sr)
+    OrEndLReplay' prEnd (Done rr) = Right  (Right rr)
+    OrEndLReplay' prEnd (Err  er) = Left   (EOrR er)
+
+type OrChSym
+    :: ParserChSym sl rl
+    -> ParserChSym sr rr
+    -> sr
+    -> ParserChSym (OrS sl sr) (Either rl rr)
+data OrChSym plCh prCh s0r f
+type instance App (OrChSym plCh prCh s0r) f = OrChSym1 plCh prCh s0r f
+
+type OrChSym1
+    :: ParserChSym sl rl
+    -> ParserChSym sr rr
+    -> sr
+    -> ParserChSym1 (OrS sl sr) (Either rl rr)
+data OrChSym1 plCh prCh sr ch s
+type instance App (OrChSym1 plCh prCh sr ch) s = OrCh plCh prCh sr ch s
+
+sOrChSym
+    :: SParserChSym ssl srl plCh
+    -> SParserChSym ssr srr prCh
+    -> ssr s0r
+    -> SParserChSym (SOrS ssl ssr) (SEither srl srr) (OrChSym plCh prCh s0r)
+sOrChSym plCh prCh s0r = Lam2 $ \ch -> \case
+  SLeft  (STuple2 sl chs) -> sOrChL prCh s0r ch chs (plCh @@ ch @@ sl)
+  SRight sr -> sOrChR (prCh @@ ch @@ sr)
+
+sOrChL
+    :: SParserChSym ssr srr prCh
+    -> ssr s0r
+    -> SChar chLast
+    -> SList SChar chs
+    -> SResult ssl srl resl
+    -> SResult (SOrS ssl ssr) (SEither srl srr) (OrChL prCh s0r chLast chs resl)
+sOrChL prCh s0r chLast chs = \case
+  SCont  sl -> SCont $ SLeft $ STuple2 sl $ SCons chLast chs
+  SDone  rl -> SDone $ SLeft rl
+  SErr  _el -> sOrChLReplay prCh chLast (sReverse chs) (SCont s0r)
+
+type OrEndSym
+    :: ParserEndSym sl rl
+    -> ParserChSym  sr rr
+    -> ParserEndSym sr rr
+    -> sr
+    -> ParserEndSym (Either (sl, [Char]) sr) (Either rl rr)
+data OrEndSym plEnd prCh prEnd s0r s
+type instance App (OrEndSym plEnd prCh prEnd s0r) s =
+    OrEnd plEnd prCh prEnd s0r s
+
+sOrEndSym
+    :: SParserEndSym ssl srl plEnd
+    -> SParserChSym  ssr srr prCh
+    -> SParserEndSym ssr srr prEnd
+    -> ssr s0r
+    -> SParserEndSym (SOrS ssl ssr) (SEither srl srr)
+        (OrEndSym plEnd prCh prEnd s0r)
+sOrEndSym plEnd prCh prEnd s0r = Lam $ \case
+  SLeft (STuple2 sl chs) -> sOrEndL prCh prEnd s0r chs (plEnd @@ sl)
+  SRight sr -> sOrEndR $ prEnd @@ sr
diff --git a/src/Symparsec/Parser/Skip.hs b/src/Symparsec/Parser/Skip.hs
--- a/src/Symparsec/Parser/Skip.hs
+++ b/src/Symparsec/Parser/Skip.hs
@@ -50,7 +50,7 @@
     SkipEnd n = Left (ESkipPastEnd n)
 
 type ESkipPastEnd n = EBase "Skip"
-    (      Text "tried to drop "
+    (      Text "tried to skip "
       :<>: Text (ShowNatDec n) :<>: Text " chars from empty string")
 eSkipPastEnd :: SNat n -> SE (ESkipPastEnd n)
 eSkipPastEnd n = withKnownSymbol (sShowNatDec n) singE
diff --git a/src/Symparsec/Parser/Take.hs b/src/Symparsec/Parser/Take.hs
--- a/src/Symparsec/Parser/Take.hs
+++ b/src/Symparsec/Parser/Take.hs
@@ -21,7 +21,7 @@
 type  TakeS = (Natural, [Char])
 
 sTake :: SNat n -> SParser STakeS SSymbol (Take n)
-sTake n = SParser takeChSym takeEndSym (STuple2 n SNil)
+sTake n = SParser sTakeChSym sTakeEndSym (STuple2 n SNil)
 
 instance KnownNat n => SingParser (Take n) where
     type PS (Take n) = STakeS
@@ -37,8 +37,8 @@
 data TakeChSym f
 type instance App TakeChSym f = TakeChSym1 f
 
-takeChSym :: SParserChSym STakeS SSymbol TakeChSym
-takeChSym = Lam2 $ \ch (STuple2 n chs) ->
+sTakeChSym :: SParserChSym STakeS SSymbol TakeChSym
+sTakeChSym = Lam2 $ \ch (STuple2 n chs) ->
     case testEquality n (SNat @0) of
       Just Refl -> SDone $ revCharsToSymbol chs
       Nothing   ->
@@ -64,8 +64,8 @@
 data TakeEndSym s
 type instance App TakeEndSym s = TakeEnd s
 
-takeEndSym :: SParserEndSym STakeS SSymbol TakeEndSym
-takeEndSym = Lam $ \(STuple2 n chs) ->
+sTakeEndSym :: SParserEndSym STakeS SSymbol TakeEndSym
+sTakeEndSym = Lam $ \(STuple2 n chs) ->
     case testEquality n (SNat @0) of
       Just Refl -> SRight $ revCharsToSymbol chs
       Nothing   -> unsafeCoerce $ SLeft $ eTakeEnd n
diff --git a/src/Symparsec/Parser/TakeRest.hs b/src/Symparsec/Parser/TakeRest.hs
new file mode 100644
--- /dev/null
+++ b/src/Symparsec/Parser/TakeRest.hs
@@ -0,0 +1,39 @@
+{-# LANGUAGE UndecidableInstances #-}
+
+module Symparsec.Parser.TakeRest where
+
+import Symparsec.Parser.Common
+import Singleraeh.Symbol ( RevCharsToSymbol, revCharsToSymbol )
+import Singleraeh.List ( SList(..) )
+import Singleraeh.Either ( SEither(..) )
+import GHC.TypeLits hiding ( ErrorMessage(..) )
+import DeFun.Core
+
+-- | Return the remaining input string.
+type TakeRest = 'PParser TakeRestChSym TakeRestEndSym '[]
+
+sTakeRest :: SParser (SList SChar) SSymbol TakeRest
+sTakeRest = SParser sTakeRestChSym sTakeRestEndSym SNil
+
+instance SingParser TakeRest where
+    type PS TakeRest = SList SChar
+    type PR TakeRest = SSymbol
+    singParser' = sTakeRest
+
+type TakeRestChSym :: ParserChSym [Char] Symbol
+data TakeRestChSym f
+type instance App TakeRestChSym f = TakeRestChSym1 f
+
+type TakeRestChSym1 :: ParserChSym1 [Char] Symbol
+data TakeRestChSym1 ch chs
+type instance App (TakeRestChSym1 ch) chs = Cont (ch : chs)
+
+sTakeRestChSym :: SParserChSym (SList SChar) SSymbol TakeRestChSym
+sTakeRestChSym = Lam2 $ \ch chs -> SCont $ SCons ch chs
+
+type TakeRestEndSym :: ParserEndSym [Char] Symbol
+data TakeRestEndSym chs
+type instance App TakeRestEndSym chs = Right (RevCharsToSymbol chs)
+
+sTakeRestEndSym :: SParserEndSym (SList SChar) SSymbol TakeRestEndSym
+sTakeRestEndSym = Lam $ \chs -> SRight $ revCharsToSymbol chs
diff --git a/src/Symparsec/Parsers.hs b/src/Symparsec/Parsers.hs
--- a/src/Symparsec/Parsers.hs
+++ b/src/Symparsec/Parsers.hs
@@ -15,6 +15,7 @@
   -- * Positional
   -- $positional
   , Take
+  , TakeRest
   , Skip
   , End
   , Isolate
@@ -40,6 +41,7 @@
 import Symparsec.Parser.Literal
 import Symparsec.Parser.End
 import Symparsec.Parser.Take
+import Symparsec.Parser.TakeRest
 --import Symparsec.Parser.Or
 
 -- $binary-combinators
diff --git a/symparsec.cabal b/symparsec.cabal
--- a/symparsec.cabal
+++ b/symparsec.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           symparsec
-version:        1.0.0
+version:        1.0.1
 synopsis:       Type level string parser combinators
 description:    Please see README.md.
 category:       Types, Data
@@ -30,7 +30,6 @@
 library
   exposed-modules:
       Symparsec
-      Symparsec.Internal.List
       Symparsec.Parser
       Symparsec.Parser.Common
       Symparsec.Parser.End
@@ -38,8 +37,10 @@
       Symparsec.Parser.Literal
       Symparsec.Parser.Natural
       Symparsec.Parser.Natural.Digits
+      Symparsec.Parser.Or
       Symparsec.Parser.Skip
       Symparsec.Parser.Take
+      Symparsec.Parser.TakeRest
       Symparsec.Parser.Then
       Symparsec.Parser.Then.VoidLeft
       Symparsec.Parser.Then.VoidRight
