diff --git a/Data/Picoparsec/Combinator.hs b/Data/Picoparsec/Combinator.hs
--- a/Data/Picoparsec/Combinator.hs
+++ b/Data/Picoparsec/Combinator.hs
@@ -32,6 +32,8 @@
     , feed
     , endOfInput
     , atEnd
+    , lookAhead
+    , notFollowedBy
     ) where
 
 import Prelude hiding (succ)
@@ -39,8 +41,9 @@
 import Control.Applicative (Alternative(..), Applicative(..), empty, liftA2,
                             many, (<|>), (*>), (<$>))
 import Control.Monad (MonadPlus(..))
-import Data.Picoparsec.Internal.Types (Parser(..))
-import Data.Picoparsec.Internal (atEnd, endOfInput, feed)
+import Data.Monoid (Monoid(mappend))
+import Data.Picoparsec.Internal.Types (Parser(..), IResult(..))
+import Data.Picoparsec.Internal (atEnd, endOfInput, lookAhead, notFollowedBy)
 import Data.ByteString (ByteString)
 import Data.Text (Text)
 import qualified Data.Picoparsec.Zepto as Z
@@ -127,7 +130,7 @@
 -- | @sepBy p sep@ applies /zero/ or more occurrences of @p@, separated
 -- by @sep@. Returns a list of the values returned by @p@.
 --
--- > commaSep p  = p `sepBy` (symbol ",")
+-- > commaSep p  = p `sepBy` (char ',')
 sepBy :: Alternative f => f a -> f s -> f [a]
 sepBy p s = liftA2 (:) p ((s *> sepBy1 p s) <|> pure []) <|> pure []
 {-# SPECIALIZE sepBy :: Parser ByteString a -> Parser ByteString s
@@ -140,7 +143,7 @@
 -- by @sep@. Returns a list of the values returned by @p@. The value
 -- returned by @p@ is forced to WHNF.
 --
--- > commaSep p  = p `sepBy'` (symbol ",")
+-- > commaSep p  = p `sepBy'` (char ',')
 sepBy' :: (MonadPlus m) => m a -> m s -> m [a]
 sepBy' p s = scan `mplus` return []
   where scan = liftM2' (:) p ((s >> sepBy1' p s) `mplus` return [])
@@ -152,7 +155,7 @@
 -- | @sepBy1 p sep@ applies /one/ or more occurrences of @p@, separated
 -- by @sep@. Returns a list of the values returned by @p@.
 --
--- > commaSep p  = p `sepBy1` (symbol ",")
+-- > commaSep p  = p `sepBy1` (char ',')
 sepBy1 :: Alternative f => f a -> f s -> f [a]
 sepBy1 p s = scan
     where scan = liftA2 (:) p ((s *> scan) <|> pure [])
@@ -166,7 +169,7 @@
 -- by @sep@. Returns a list of the values returned by @p@. The value
 -- returned by @p@ is forced to WHNF.
 --
--- > commaSep p  = p `sepBy1'` (symbol ",")
+-- > commaSep p  = p `sepBy1'` (char ',')
 sepBy1' :: (MonadPlus m) => m a -> m s -> m [a]
 sepBy1' p s = scan
     where scan = liftM2' (:) p ((s >> scan) `mplus` return [])
@@ -240,3 +243,11 @@
 eitherP :: (Alternative f) => f a -> f b -> f (Either a b)
 eitherP a b = (Left <$> a) <|> (Right <$> b)
 {-# INLINE eitherP #-}
+
+-- | If a parser has returned a 'T.Partial' result, supply it with more
+-- input.
+feed :: Monoid i => IResult i r -> i -> IResult i r
+feed (Fail t ctxs msg) d = Fail (mappend t d) ctxs msg
+feed (Partial k) d    = k d
+feed (Done t r) d     = Done (mappend t d) r
+{-# INLINE feed #-}
diff --git a/Data/Picoparsec/Internal.hs b/Data/Picoparsec/Internal.hs
--- a/Data/Picoparsec/Internal.hs
+++ b/Data/Picoparsec/Internal.hs
@@ -19,16 +19,17 @@
     , prompt
     , demandInput
     , wantInput
-    , feed
     , endOfInput
     , atEnd
+    , lookAhead
+    , notFollowedBy
     ) where
 
 import Prelude hiding (null)
 
 import Control.Applicative ((<$>))
 import Data.Picoparsec.Internal.Types
-import Data.Monoid (Monoid(mappend), (<>))
+import Data.Monoid (Monoid, mempty, (<>))
 import Data.Monoid.Null (MonoidNull(null))
 
 -- | Compare two 'IResult' values for equality.
@@ -110,10 +111,18 @@
 atEnd = not <$> wantInput
 {-# INLINE atEnd #-}
 
--- | If a parser has returned a 'T.Partial' result, supply it with more
--- input.
-feed :: Monoid i => IResult i r -> i -> IResult i r
-feed f@(Fail _ _ _) _ = f
-feed (Partial k) d    = k d
-feed (Done t r) d     = Done (mappend t d) r
-{-# INLINE feed #-}
+-- | Apply a parser without consuming any input.
+lookAhead :: Monoid i => Parser i a -> Parser i a
+lookAhead p = Parser $ \i a more kf ks ->
+  let ks' _i' a' more' = ks (i <> I (unA a')) (a <> a') (more <> more')
+      kf' _i' a' more' = kf i (a <> a') (more <> more')
+  in runParser p i mempty more kf' ks'
+{-# INLINE lookAhead #-}
+
+-- | Apply a parser without consuming any input, and succeed if and only if the parser fails.
+notFollowedBy :: (Monoid i, Show a) => Parser i a -> Parser i ()
+notFollowedBy p = Parser $ \i a more kf ks ->
+  let ks' _i' a' more' r = kf i (a <> a') (more <> more') [] ("notFollowedBy " ++ show r)
+      kf' _i' a' more' _ _ = ks (i <> I (unA a')) (a <> a') (more <> more') ()
+  in runParser p i mempty more kf' ks'
+{-# INLINE notFollowedBy #-}
diff --git a/Data/Picoparsec/Internal/Types.hs b/Data/Picoparsec/Internal/Types.hs
--- a/Data/Picoparsec/Internal/Types.hs
+++ b/Data/Picoparsec/Internal/Types.hs
@@ -52,10 +52,13 @@
     -- not yet been consumed (if any) when the parse succeeded.
 
 instance (Show i, Show r) => Show (IResult i r) where
-    show (Fail t stk msg) =
-      unwords [ "Fail", show t, show stk, show msg]
-    show (Partial _)          = "Partial _"
-    show (Done t r)       = unwords ["Done", show t, show r]
+    showsPrec d ir = showParen (d > 10) $
+      case ir of
+        (Fail t stk msg) -> showString "Fail" . f t . f stk . f msg
+        (Partial _)      -> showString "Partial _"
+        (Done t r)       -> showString "Done" . f t . f r
+      where f :: Show a => a -> ShowS
+            f x = showChar ' ' . showsPrec 11 x
 
 instance (NFData i, NFData r) => NFData (IResult i r) where
     rnf (Fail t stk msg) = rnf t `seq` rnf stk `seq` rnf msg
diff --git a/picoparsec.cabal b/picoparsec.cabal
--- a/picoparsec.cabal
+++ b/picoparsec.cabal
@@ -1,5 +1,5 @@
 name:            picoparsec
-version:         0.1.1
+version:         0.1.2
 license:         BSD3
 license-file:    LICENSE
 category:        Text, Parsing
diff --git a/tests/QC/Combinator.hs b/tests/QC/Combinator.hs
--- a/tests/QC/Combinator.hs
+++ b/tests/QC/Combinator.hs
@@ -1,6 +1,10 @@
+{-# LANGUAGE OverloadedStrings #-}
+
 module QC.Combinator where
 
 import Control.Applicative ((<$>), (<*>))
+import Data.List (isPrefixOf)
+import Data.Maybe (fromJust, isJust)
 import Data.Monoid (mempty)
 import Data.Word (Word8)
 import QC.Common (Repack, parse, repackBS, toStrictBS)
@@ -24,6 +28,23 @@
     (length <$> parse (C.count n (P.string s)) (BL.toStrict input)) == Just n
   where input = repackBS rs (B8.concat (replicate (n+1) s))
 
+lookAhead :: NonEmptyList Word8 -> Bool
+lookAhead (NonEmpty xs) =
+  let ys = B.pack xs
+      withLookAheadThenConsume = (,) <$> C.lookAhead (P.string ys) <*> P.string ys
+      mr = parse withLookAheadThenConsume ys
+  in isJust mr && fst (fromJust mr) == snd (fromJust mr)
+
+notFollowedBy :: NonEmptyList Word8 -> NonEmptyList Word8 -> Bool
+notFollowedBy (NonEmpty xs) (NonEmpty ys) =
+  let xs' = B.pack xs
+      ys' = B.pack ys
+      withNotFollowedByThenConsume = (,) <$> C.notFollowedBy (P.string xs') <*> P.string ys'
+      mr = parse withNotFollowedByThenConsume ys'
+  in mr == if xs `isPrefixOf` ys || ys `isPrefixOf` xs
+           then Nothing
+           else Just ((), ys')
+
 {-
 match :: Int -> NonNegative Int -> NonNegative Int -> Repack -> Bool
 match n (NonNegative x) (NonNegative y) rs =
@@ -40,4 +61,6 @@
     testProperty "choice" choice
   , testProperty "count" count
 --  , testProperty "match" match
+  , testProperty "lookAhead" lookAhead
+  , testProperty "notFollowedBy" notFollowedBy
   ]
