diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,28 @@
+## Megaparsec 6.4.0
+
+* `Text.Megaparsec` now re-exports `Control.Monad.Combinators` instead of
+  `Control.Applicative.Combinators` from `parser-combinators` because the
+  monadic counterparts of the familiar combinators are more efficient and
+  not as leaky.
+
+  This may cause minor breakage in certain cases:
+
+  * You import `Control.Applicative` and in that case there will be a name
+    conflict between `Control.Applicative.many` and
+    `Control.Monad.Combinator.many` now (the same for `some`).
+
+  * You define a polymorphic helper in terms of combinator(s) from
+    `Control.Applicative.Combinators` and use `Applicative` or `Alternative`
+    constraint. In this case you'll have to adjust the constraint to be
+    `Monad` or `MonadPlus` respectively.
+
+  Also note that the new `Control.Monad.Combinators` module we re-export now
+  re-exports `empty` from `Control.Applicative`.
+
+* Fix the `atEnd` parser. It now does not produce hints, so when you use it,
+  it won't contribute to the “expecting end of input” component of parse
+  error.
+
 ## Megaparsec 6.3.0
 
 * Added an `IsString` instance for `ParsecT`. Now it is possible to
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -33,8 +33,8 @@
 * [License](#license)
 
 This is an industrial-strength monadic parser combinator library. Megaparsec
-is a fork of [Parsec](https://github.com/haskell/parsec) library originally
-written by Daan Leijen.
+is a feature-rich package that strikes a nice balance between speed,
+flexibility, and quality of parse errors.
 
 ## Features
 
@@ -387,6 +387,8 @@
 
 ## Prominent projects that use Megaparsec
 
+* [Idris](https://github.com/idris-lang/Idris-dev)—a general-purpose
+  functional programming language with dependent types
 * [Hledger](https://github.com/simonmichael/hledger)—an accounting tool
 * [Stache](https://github.com/stackbuilders/stache)—Mustache templates for Haskell
 * [Language Puppet](https://github.com/bartavelle/language-puppet)—library
diff --git a/Text/Megaparsec.hs b/Text/Megaparsec.hs
--- a/Text/Megaparsec.hs
+++ b/Text/Megaparsec.hs
@@ -77,7 +77,7 @@
     module Text.Megaparsec.Pos
   , module Text.Megaparsec.Error
   , module Text.Megaparsec.Stream
-  , module Control.Applicative.Combinators
+  , module Control.Monad.Combinators
     -- * Data types
   , State (..)
   , Parsec
@@ -118,9 +118,9 @@
   , dbg )
 where
 
-import Control.Applicative.Combinators
 import Control.DeepSeq
 import Control.Monad
+import Control.Monad.Combinators
 import Control.Monad.Cont.Class
 import Control.Monad.Error.Class
 import Control.Monad.Identity
@@ -159,14 +159,14 @@
 
 -- $reexports
 --
--- Also note that you can import "Control.Applicative.Combinators.NonEmpty"
--- if you wish that combinators like 'some' return 'NonEmpty' lists. The
--- module lives in the @parser-combinators@ package (you need at least
--- version /0.2.0/).
+-- Also note that you can import "Control.Monad.Combinators.NonEmpty" if you
+-- wish that combinators like 'some' return 'NonEmpty' lists. The module
+-- lives in the @parser-combinators@ package (you need at least version
+-- /0.4.0/).
 --
 -- This module is intended to be imported qualified:
 --
--- > import qualified Control.Applicative.Combinators.NonEmpty as NE
+-- > import qualified Control.Monad.Combinators.NonEmpty as NE
 
 ----------------------------------------------------------------------------
 -- Data types
@@ -1406,7 +1406,7 @@
 -- @since 6.0.0
 
 atEnd :: MonadParsec e s m => m Bool
-atEnd = option False (True <$ eof)
+atEnd = option False (True <$ hidden eof)
 {-# INLINE atEnd #-}
 
 ----------------------------------------------------------------------------
diff --git a/Text/Megaparsec/Char/Lexer.hs b/Text/Megaparsec/Char/Lexer.hs
--- a/Text/Megaparsec/Char/Lexer.hs
+++ b/Text/Megaparsec/Char/Lexer.hs
@@ -561,7 +561,7 @@
   => m ()              -- ^ How to consume white space after the sign
   -> m a               -- ^ How to parse the number itself
   -> m a               -- ^ Parser for signed numbers
-signed spc p = ($) <$> option id (lexeme spc sign) <*> p
+signed spc p = option id (lexeme spc sign) <*> p
   where
     sign = (id <$ C.char '+') <|> (negate <$ C.char '-')
 {-# INLINEABLE signed #-}
diff --git a/Text/Megaparsec/Perm.hs b/Text/Megaparsec/Perm.hs
--- a/Text/Megaparsec/Perm.hs
+++ b/Text/Megaparsec/Perm.hs
@@ -29,7 +29,7 @@
 import Text.Megaparsec
 
 #if !MIN_VERSION_base(4,8,0)
-import Control.Applicative ((<$>), (<*>))
+import Control.Applicative
 #endif
 
 infixl 1 <||>, <|?>
@@ -61,10 +61,11 @@
 makePermParser :: MonadParsec e s m
   => PermParser s m a -- ^ Given permutation parser
   -> m a              -- ^ Normal parser built from it
-makePermParser (Perm def xs) = choice (fmap branch xs ++ empty)
-  where empty = case def of
-                  Nothing -> []
-                  Just x  -> [return x]
+makePermParser (Perm def xs) = choice (fmap branch xs ++ empty')
+  where empty' =
+          case def of
+            Nothing -> []
+            Just x  -> [return x]
         branch (Branch perm p) = flip ($) <$> p <*> makePermParser perm
 
 -- | The expression @f \<$$> p@ creates a fresh permutation parser
diff --git a/bench/memory/Main.hs b/bench/memory/Main.hs
--- a/bench/memory/Main.hs
+++ b/bench/memory/Main.hs
@@ -37,6 +37,7 @@
   bparser "sepEndBy1" manyAbs' (const $ sepEndBy1 (char 'a') (char 'b'))
   bparser "skipMany" manyAs (const $ skipMany (char 'a'))
   bparser "skipSome" manyAs (const $ skipSome (char 'a'))
+  bparser "skipCount" manyAs (\(_,n) -> skipCount n (char 'a'))
   bparser "skipManyTill" manyAsB (const $ skipManyTill (char 'a') (char 'b'))
   bparser "skipSomeTill" manyAsB (const $ skipSomeTill (char 'a') (char 'b'))
   bparser "takeWhileP" manyAs (const $ takeWhileP Nothing (== 'a'))
diff --git a/bench/speed/Main.hs b/bench/speed/Main.hs
--- a/bench/speed/Main.hs
+++ b/bench/speed/Main.hs
@@ -35,6 +35,7 @@
   , bparser "sepEndBy1" manyAbs' (const $ sepEndBy1 (char 'a') (char 'b'))
   , bparser "skipMany" manyAs (const $ skipMany (char 'a'))
   , bparser "skipSome" manyAs (const $ skipSome (char 'a'))
+  , bparser "skipCount" manyAs (\(_,n) -> skipCount n (char 'a'))
   , bparser "skipManyTill" manyAsB (const $ skipManyTill (char 'a') (char 'b'))
   , bparser "skipSomeTill" manyAsB (const $ skipSomeTill (char 'a') (char 'b'))
   , bparser "takeWhileP" manyAs (const $ takeWhileP Nothing (== 'a'))
diff --git a/megaparsec.cabal b/megaparsec.cabal
--- a/megaparsec.cabal
+++ b/megaparsec.cabal
@@ -1,5 +1,5 @@
 name:                 megaparsec
-version:              6.3.0
+version:              6.4.0
 cabal-version:        >= 1.18
 tested-with:          GHC==7.8.4, GHC==7.10.3, GHC==8.0.2, GHC==8.2.2
 license:              BSD2
@@ -16,8 +16,9 @@
 build-type:           Simple
 description:
 
-  This is industrial-strength monadic parser combinator library. Megaparsec
-  is a fork of Parsec library originally written by Daan Leijen.
+  This is an industrial-strength monadic parser combinator library.
+  Megaparsec is a feature-rich package that strikes a nice balance between
+  speed, flexibility, and quality of parse errors.
 
 extra-doc-files:      AUTHORS.md
                     , CHANGELOG.md
@@ -39,7 +40,7 @@
                     , containers   >= 0.5   && < 0.6
                     , deepseq      >= 1.3   && < 1.5
                     , mtl          >= 2.0   && < 3.0
-                    , parser-combinators >= 0.1 && < 0.3
+                    , parser-combinators >= 0.4 && < 1.0
                     , scientific   >= 0.3.1 && < 0.4
                     , text         >= 0.2   && < 1.3
                     , transformers >= 0.4   && < 0.6
@@ -74,6 +75,7 @@
   else
     ghc-options:      -O2 -Wall
   other-modules:      Control.Applicative.CombinatorsSpec
+                    , Control.Monad.CombinatorsSpec
                     , Test.Hspec.Megaparsec
                     , Test.Hspec.Megaparsec.AdHoc
                     , Text.Megaparsec.Byte.LexerSpec
diff --git a/tests/Control/Applicative/CombinatorsSpec.hs b/tests/Control/Applicative/CombinatorsSpec.hs
--- a/tests/Control/Applicative/CombinatorsSpec.hs
+++ b/tests/Control/Applicative/CombinatorsSpec.hs
@@ -1,8 +1,8 @@
+{-# LANGUAGE CPP        #-}
 {-# LANGUAGE MultiWayIf #-}
 
 module Control.Applicative.CombinatorsSpec (spec) where
 
-import Control.Applicative
 import Data.Char (isLetter, isDigit)
 import Data.List (intersperse)
 import Data.Maybe (fromMaybe, maybeToList, isNothing, fromJust)
@@ -14,228 +14,268 @@
 import Text.Megaparsec
 import Text.Megaparsec.Char
 
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative hiding (many, some)
+#endif
+
 spec :: Spec
 spec = do
 
-  describe "between" . it "works" . property $ \pre c n' post -> do
-    let p = between (string pre) (string post) (many (char c))
-        n = getNonNegative n'
-        b = length (takeWhile (== c) post)
-        z = replicate n c
-        s = pre ++ z ++ post
-    if b > 0
-      then prs_ p s `shouldFailWith` err (posN (length pre + n + b) s)
-        ( etoks post <> etok c <>
-          if length post == b
-            then ueof
-            else utoks (drop b post) )
-      else prs_ p s `shouldParse` z
+  describe "between" $
+    it "works" . property $ \pre c n' post -> do
+      let p = between (string pre) (string post) (many (char c))
+          n = getNonNegative n'
+          b = length (takeWhile (== c) post)
+          z = replicate n c
+          s = pre ++ z ++ post
+      if b > 0
+        then prs_ p s `shouldFailWith` err (posN (length pre + n + b) s)
+          ( etoks post <> etok c <>
+            if length post == b
+              then ueof
+              else utoks (drop b post) )
+        else prs_ p s `shouldParse` z
 
-  describe "choice" . it "works" . property $ \cs' s' -> do
-    let cs = getNonEmpty cs'
-        p = choice (char <$> cs)
-        s = [s']
-    if s' `elem` cs
-      then prs_ p s `shouldParse` s'
-      else prs_ p s `shouldFailWith` err posI (utok s' <> mconcat (etok <$> cs))
+  describe "choice" $
+    it "works" . property $ \cs' s' -> do
+      let cs = getNonEmpty cs'
+          p = choice (char <$> cs)
+          s = [s']
+      if s' `elem` cs
+        then prs_ p s `shouldParse` s'
+        else prs_ p s `shouldFailWith` err posI (utok s' <> mconcat (etok <$> cs))
 
-  describe "count" . it "works" . property $ \n x' -> do
-    let x = getNonNegative x'
-        p = count n (char 'x')
-        p' = count' n n (char 'x')
-        s = replicate x 'x'
-    prs_ p s `shouldBe` prs_ p' s
+  describe "count" $ do
+    it "works" . property $ \n x' -> do
+      let x = getNonNegative x'
+          p = count n (char 'x')
+          p' = count' n n (char 'x')
+          s = replicate x 'x'
+      prs_ p s `shouldBe` prs_ p' s
+    rightOrder (count 3 letterChar) "abc" "abc"
 
-  describe "count'" . it "works" . property $ \m n x' -> do
-    let x = getNonNegative x'
-        p = count' m n (char 'x')
-        s = replicate x 'x'
-    if | n <= 0 || m > n ->
-         if x == 0
-           then prs_ p s `shouldParse` ""
-           else prs_ p s `shouldFailWith` err posI (utok 'x' <> eeof)
-       | m <= x && x <= n ->
-         prs_ p s `shouldParse` s
-       | x < m ->
-         prs_ p s `shouldFailWith` err (posN x s) (ueof <> etok 'x')
-       | otherwise ->
-         prs_ p s `shouldFailWith` err (posN n s) (utok 'x' <> eeof)
+  describe "count'" $ do
+    it "works" . property $ \m n x' -> do
+      let x = getNonNegative x'
+          p = count' m n (char 'x')
+          s = replicate x 'x'
+      if | n <= 0 || m > n ->
+           if x == 0
+             then prs_ p s `shouldParse` ""
+             else prs_ p s `shouldFailWith` err posI (utok 'x' <> eeof)
+         | m <= x && x <= n ->
+           prs_ p s `shouldParse` s
+         | x < m ->
+           prs_ p s `shouldFailWith` err (posN x s) (ueof <> etok 'x')
+         | otherwise ->
+           prs_ p s `shouldFailWith` err (posN n s) (utok 'x' <> eeof)
+    rightOrder (count' 1 3 letterChar) "abc" "abc"
 
-  describe "eitherP" . it "works" . property $ \ch -> do
-    let p = eitherP letterChar digitChar
-        s = pure ch
-    if | isLetter ch -> prs_ p s `shouldParse` Left ch
-       | isDigit  ch -> prs_ p s `shouldParse` Right ch
-       | otherwise   -> prs_ p s `shouldFailWith`
-         err posI (utok ch <> elabel "letter" <> elabel "digit")
+  describe "eitherP" $
+    it "works" . property $ \ch -> do
+      let p = eitherP letterChar digitChar
+          s = pure ch
+      if | isLetter ch -> prs_ p s `shouldParse` Left ch
+         | isDigit  ch -> prs_ p s `shouldParse` Right ch
+         | otherwise   -> prs_ p s `shouldFailWith`
+           err posI (utok ch <> elabel "letter" <> elabel "digit")
 
-  describe "endBy" . it "works" . property $ \n' c -> do
-    let n = getNonNegative n'
-        p = endBy (char 'a') (char '-')
-        s = intersperse '-' (replicate n 'a') ++ [c]
-    if | c == 'a' && n == 0 ->
-         prs_ p s `shouldFailWith` err (posN (1 :: Int) s) (ueof <> etok '-')
-       | c == 'a' ->
-         prs_ p s `shouldFailWith` err (posN (g n) s) (utok 'a' <> etok '-')
-       | c == '-' && n == 0 ->
-         prs_ p s `shouldFailWith` err posI (utok '-' <> etok 'a'<> eeof)
-       | c /= '-' ->
-         prs_ p s `shouldFailWith` err (posN (g n) s)
-           ( utok c <>
-             (if n > 0 then etok '-' else eeof) <>
-             (if n == 0 then etok 'a' else mempty) )
-       | otherwise -> prs_ p s `shouldParse` replicate n 'a'
+  describe "endBy" $ do
+    it "works" . property $ \n' c -> do
+      let n = getNonNegative n'
+          p = endBy (char 'a') (char '-')
+          s = intersperse '-' (replicate n 'a') ++ [c]
+      if | c == 'a' && n == 0 ->
+           prs_ p s `shouldFailWith` err (posN (1 :: Int) s) (ueof <> etok '-')
+         | c == 'a' ->
+           prs_ p s `shouldFailWith` err (posN (g n) s) (utok 'a' <> etok '-')
+         | c == '-' && n == 0 ->
+           prs_ p s `shouldFailWith` err posI (utok '-' <> etok 'a'<> eeof)
+         | c /= '-' ->
+           prs_ p s `shouldFailWith` err (posN (g n) s)
+             ( utok c <>
+               (if n > 0 then etok '-' else eeof) <>
+               (if n == 0 then etok 'a' else mempty) )
+         | otherwise -> prs_ p s `shouldParse` replicate n 'a'
+    rightOrder (endBy letterChar (char ',')) "a,b,c," "abc"
 
-  describe "endBy1" . it "works" . property $ \n' c -> do
-    let n = getNonNegative n'
-        p = endBy1 (char 'a') (char '-')
-        s = intersperse '-' (replicate n 'a') ++ [c]
-    if | c == 'a' && n == 0 ->
-         prs_ p s `shouldFailWith` err (posN (1 :: Int) s) (ueof <> etok '-')
-       | c == 'a' ->
-         prs_ p s `shouldFailWith` err (posN (g n) s) (utok 'a' <> etok '-')
-       | c == '-' && n == 0 ->
-         prs_ p s `shouldFailWith` err posI (utok '-' <> etok 'a')
-       | c /= '-' ->
-         prs_ p s `shouldFailWith` err (posN (g n) s)
-           ( utok c <>
-             (if n > 0 then etok '-' else mempty) <>
-             (if n == 0 then etok 'a' else mempty) )
-       | otherwise -> prs_ p s `shouldParse` replicate n 'a'
+  describe "endBy1" $ do
+    it "works" . property $ \n' c -> do
+      let n = getNonNegative n'
+          p = endBy1 (char 'a') (char '-')
+          s = intersperse '-' (replicate n 'a') ++ [c]
+      if | c == 'a' && n == 0 ->
+           prs_ p s `shouldFailWith` err (posN (1 :: Int) s) (ueof <> etok '-')
+         | c == 'a' ->
+           prs_ p s `shouldFailWith` err (posN (g n) s) (utok 'a' <> etok '-')
+         | c == '-' && n == 0 ->
+           prs_ p s `shouldFailWith` err posI (utok '-' <> etok 'a')
+         | c /= '-' ->
+           prs_ p s `shouldFailWith` err (posN (g n) s)
+             ( utok c <>
+               (if n > 0 then etok '-' else mempty) <>
+               (if n == 0 then etok 'a' else mempty) )
+         | otherwise -> prs_ p s `shouldParse` replicate n 'a'
+    rightOrder (endBy1 letterChar (char ',')) "a,b,c," "abc"
 
-  describe "manyTill" . it "works" . property $ \a' b' c' -> do
-    let [a,b,c] = getNonNegative <$> [a',b',c']
-        p = (,) <$> manyTill letterChar (char 'c') <*> many letterChar
-        s = abcRow a b c
-    if c == 0
-      then prs_ p s `shouldFailWith` err (posN (a + b) s)
-           (ueof <> etok 'c' <> elabel "letter")
-      else let (pre, post) = break (== 'c') s
+  describe "manyTill" $ do
+    it "works" . property $ \a' b' c' -> do
+      let [a,b,c] = getNonNegative <$> [a',b',c']
+          p = (,) <$> manyTill letterChar (char 'c') <*> many letterChar
+          s = abcRow a b c
+      if c == 0
+        then prs_ p s `shouldFailWith` err (posN (a + b) s)
+             (ueof <> etok 'c' <> elabel "letter")
+        else let (pre, post) = break (== 'c') s
+             in prs_ p s `shouldParse` (pre, drop 1 post)
+    rightOrder (manyTill letterChar (char 'd')) "abcd" "abc"
+
+  describe "someTill" $ do
+    it "works" . property $ \a' b' c' -> do
+      let [a,b,c] = getNonNegative <$> [a',b',c']
+          p = (,) <$> someTill letterChar (char 'c') <*> many letterChar
+          s = abcRow a b c
+      if | null s ->
+           prs_ p s `shouldFailWith` err posI (ueof <> elabel "letter")
+         | c == 0 ->
+           prs_ p s `shouldFailWith` err (posN (a + b) s)
+             (ueof <> etok 'c' <> elabel "letter")
+         | s == "c" ->
+           prs_ p s `shouldFailWith` err
+             (posN (1 :: Int) s) (ueof <> etok 'c' <> elabel "letter")
+         | head s == 'c' ->
+           prs_ p s `shouldParse` ("c", drop 2 s)
+         | otherwise ->
+           let (pre, post) = break (== 'c') s
            in prs_ p s `shouldParse` (pre, drop 1 post)
+    rightOrder (someTill letterChar (char 'd')) "abcd" "abc"
 
-  describe "someTill" . it "works" . property $ \a' b' c' -> do
-    let [a,b,c] = getNonNegative <$> [a',b',c']
-        p = (,) <$> someTill letterChar (char 'c') <*> many letterChar
-        s = abcRow a b c
-    if | null s ->
-         prs_ p s `shouldFailWith` err posI (ueof <> elabel "letter")
-       | c == 0 ->
-         prs_ p s `shouldFailWith` err (posN (a + b) s)
-           (ueof <> etok 'c' <> elabel "letter")
-       | s == "c" ->
-         prs_ p s `shouldFailWith` err
-           (posN (1 :: Int) s) (ueof <> etok 'c' <> elabel "letter")
-       | head s == 'c' ->
-         prs_ p s `shouldParse` ("c", drop 2 s)
-       | otherwise ->
-         let (pre, post) = break (== 'c') s
-         in prs_ p s `shouldParse` (pre, drop 1 post)
+  describe "option" $
+    it "works" . property $ \d a s -> do
+      let p = option d (string a)
+          p' = fromMaybe d <$> optional (string a)
+      prs_ p s `shouldBe` prs_ p' s
 
-  describe "option" . it "works" . property $ \d a s -> do
-    let p = option d (string a)
-        p' = fromMaybe d <$> optional (string a)
-    prs_ p s `shouldBe` prs_ p' s
+  describe "sepBy" $ do
+    it "works" . property $ \n' c' -> do
+      let n = getNonNegative n'
+          c = fromJust c'
+          p = sepBy (char 'a') (char '-')
+          s = intersperse '-' (replicate n 'a') ++ maybeToList c'
+      if | isNothing c' ->
+           prs_ p s `shouldParse` replicate n 'a'
+         | c == 'a' && n == 0 ->
+           prs_ p s `shouldParse` "a"
+         | n == 0 ->
+           prs_ p s `shouldFailWith` err posI
+             (utok c <> etok 'a' <> eeof)
+         | c == '-' ->
+           prs_ p s `shouldFailWith` err (posN (length s) s)
+             (ueof <> etok 'a')
+         | otherwise ->
+           prs_ p s `shouldFailWith` err (posN (g n) s)
+             (utok c <> etok '-' <> eeof)
+    rightOrder (sepBy letterChar (char ',')) "a,b,c" "abc"
 
-  describe "sepBy" . it "works" . property $ \n' c' -> do
-    let n = getNonNegative n'
-        c = fromJust c'
-        p = sepBy (char 'a') (char '-')
-        s = intersperse '-' (replicate n 'a') ++ maybeToList c'
-    if | isNothing c' ->
-         prs_ p s `shouldParse` replicate n 'a'
-       | c == 'a' && n == 0 ->
-         prs_ p s `shouldParse` "a"
-       | n == 0 ->
-         prs_ p s `shouldFailWith` err posI
-           (utok c <> etok 'a' <> eeof)
-       | c == '-' ->
-         prs_ p s `shouldFailWith` err (posN (length s) s)
-           (ueof <> etok 'a')
-       | otherwise ->
-         prs_ p s `shouldFailWith` err (posN (g n) s)
-           (utok c <> etok '-' <> eeof)
+  describe "sepBy1" $ do
+    it "works" . property $ \n' c' -> do
+      let n = getNonNegative n'
+          c = fromJust c'
+          p = sepBy1 (char 'a') (char '-')
+          s = intersperse '-' (replicate n 'a') ++ maybeToList c'
+      if | isNothing c' && n >= 1 ->
+           prs_ p s `shouldParse` replicate n 'a'
+         | isNothing c' ->
+           prs_ p s `shouldFailWith` err posI (ueof <> etok 'a')
+         | c == 'a' && n == 0 ->
+           prs_ p s `shouldParse` "a"
+         | n == 0 ->
+           prs_ p s `shouldFailWith` err posI (utok c <> etok 'a')
+         | c == '-' ->
+           prs_ p s `shouldFailWith` err (posN (length s) s) (ueof <> etok 'a')
+         | otherwise ->
+           prs_ p s `shouldFailWith` err (posN (g n) s) (utok c <> etok '-' <> eeof)
+    rightOrder (sepBy1 letterChar (char ',')) "a,b,c" "abc"
 
-  describe "sepBy1" . it "works" . property $ \n' c' -> do
-    let n = getNonNegative n'
-        c = fromJust c'
-        p = sepBy1 (char 'a') (char '-')
-        s = intersperse '-' (replicate n 'a') ++ maybeToList c'
-    if | isNothing c' && n >= 1 ->
-         prs_ p s `shouldParse` replicate n 'a'
-       | isNothing c' ->
-         prs_ p s `shouldFailWith` err posI (ueof <> etok 'a')
-       | c == 'a' && n == 0 ->
-         prs_ p s `shouldParse` "a"
-       | n == 0 ->
-         prs_ p s `shouldFailWith` err posI (utok c <> etok 'a')
-       | c == '-' ->
-         prs_ p s `shouldFailWith` err (posN (length s) s) (ueof <> etok 'a')
-       | otherwise ->
-         prs_ p s `shouldFailWith` err (posN (g n) s) (utok c <> etok '-' <> eeof)
+  describe "sepEndBy" $ do
+    it "works" . property $ \n' c' -> do
+      let n = getNonNegative n'
+          c = fromJust c'
+          p = sepEndBy (char 'a') (char '-')
+          a = replicate n 'a'
+          s = intersperse '-' (replicate n 'a') ++ maybeToList c'
+      if | isNothing c' ->
+           prs_ p s `shouldParse` a
+         | c == 'a' && n == 0 ->
+           prs_ p s `shouldParse` "a"
+         | n == 0 ->
+           prs_ p s `shouldFailWith` err posI (utok c <> etok 'a' <> eeof)
+         | c == '-' ->
+           prs_ p s `shouldParse` a
+         | otherwise ->
+           prs_ p s `shouldFailWith` err (posN (g n) s) (utok c <> etok '-' <> eeof)
+    rightOrder (sepEndBy letterChar (char ',')) "a,b,c," "abc"
 
-  describe "sepEndBy" . it "works" . property $ \n' c' -> do
-    let n = getNonNegative n'
-        c = fromJust c'
-        p = sepEndBy (char 'a') (char '-')
-        a = replicate n 'a'
-        s = intersperse '-' (replicate n 'a') ++ maybeToList c'
-    if | isNothing c' ->
-         prs_ p s `shouldParse` a
-       | c == 'a' && n == 0 ->
-         prs_ p s `shouldParse` "a"
-       | n == 0 ->
-         prs_ p s `shouldFailWith` err posI (utok c <> etok 'a' <> eeof)
-       | c == '-' ->
-         prs_ p s `shouldParse` a
-       | otherwise ->
-         prs_ p s `shouldFailWith` err (posN (g n) s) (utok c <> etok '-' <> eeof)
+  describe "sepEndBy1" $ do
+    it "works" . property $ \n' c' -> do
+      let n = getNonNegative n'
+          c = fromJust c'
+          p = sepEndBy1 (char 'a') (char '-')
+          a = replicate n 'a'
+          s = intersperse '-' (replicate n 'a') ++ maybeToList c'
+      if | isNothing c' && n >= 1 ->
+           prs_ p s `shouldParse` a
+         | isNothing c' ->
+           prs_ p s `shouldFailWith` err posI (ueof <> etok 'a')
+         | c == 'a' && n == 0 ->
+           prs_ p s `shouldParse` "a"
+         | n == 0 ->
+           prs_ p s `shouldFailWith` err posI (utok c <> etok 'a')
+         | c == '-' ->
+           prs_ p s `shouldParse` a
+         | otherwise ->
+           prs_ p s `shouldFailWith` err (posN (g n) s) (utok c <> etok '-' <> eeof)
+    rightOrder (sepEndBy1 letterChar (char ',')) "a,b,c," "abc"
 
-  describe "sepEndBy1" . it "works" . property $ \n' c' -> do
-    let n = getNonNegative n'
-        c = fromJust c'
-        p = sepEndBy1 (char 'a') (char '-')
-        a = replicate n 'a'
-        s = intersperse '-' (replicate n 'a') ++ maybeToList c'
-    if | isNothing c' && n >= 1 ->
-         prs_ p s `shouldParse` a
-       | isNothing c' ->
-         prs_ p s `shouldFailWith` err posI (ueof <> etok 'a')
-       | c == 'a' && n == 0 ->
-         prs_ p s `shouldParse` "a"
-       | n == 0 ->
-         prs_ p s `shouldFailWith` err posI (utok c <> etok 'a')
-       | c == '-' ->
-         prs_ p s `shouldParse` a
-       | otherwise ->
-         prs_ p s `shouldFailWith` err (posN (g n) s) (utok c <> etok '-' <> eeof)
+  describe "skipMany" $
+    it "works" . property $ \c n' a -> do
+      let p = skipMany (char c) *> string a
+          n = getNonNegative n'
+          p' = many (char c) >> string a
+          s = replicate n c ++ a
+      prs_ p s `shouldBe` prs_ p' s
 
-  describe "skipMany" . it "works" . property $ \c n' a -> do
-    let p = skipMany (char c) *> string a
-        n = getNonNegative n'
-        p' = many (char c) >> string a
-        s = replicate n c ++ a
-    prs_ p s `shouldBe` prs_ p' s
+  describe "skipSome" $
+    it "works" . property $ \c n' a -> do
+      let p = skipSome (char c) *> string a
+          n = getNonNegative n'
+          p' = some (char c) >> string a
+          s = replicate n c ++ a
+      prs_ p s `shouldBe` prs_ p' s
 
-  describe "skipSome" . it "works" . property $ \c n' a -> do
-    let p = skipSome (char c) *> string a
-        n = getNonNegative n'
-        p' = some (char c) >> string a
-        s = replicate n c ++ a
-    prs_ p s `shouldBe` prs_ p' s
+  describe "skipCount" $
+    it "works" . property $ \c n' a -> do
+      let p = skipCount n (char c) *> string a
+          n = getNonNegative n'
+          p' = count n (char c) *> string a
+          s = replicate n c ++ a
+      prs_ p s `shouldBe` prs_ p' s
 
-  describe "skipManyTill" . it "works" . property $ \c n' a -> c /= a ==> do
-    let p = skipManyTill (char c) (char a)
-        n = getNonNegative n'
-        s = replicate n c ++ [a]
-    prs_ p s `shouldParse` a
+  describe "skipManyTill" $
+    it "works" . property $ \c n' a -> c /= a ==> do
+      let p = skipManyTill (char c) (char a)
+          n = getNonNegative n'
+          s = replicate n c ++ [a]
+      prs_ p s `shouldParse` a
 
-  describe "skipSomeTill" . it "works" . property $ \c n' a -> c /= a ==> do
-    let p = skipSomeTill (char c) (char a)
-        n = getNonNegative n'
-        s = replicate n c ++ [a]
-    if n == 0
-      then prs_ p s `shouldFailWith` err posI (utok a <> etok c)
-      else prs_ p s `shouldParse` a
+  describe "skipSomeTill" $
+    it "works" . property $ \c n' a -> c /= a ==> do
+      let p = skipSomeTill (char c) (char a)
+          n = getNonNegative n'
+          s = replicate n c ++ [a]
+      if n == 0
+        then prs_ p s `shouldFailWith` err posI (utok a <> etok c)
+        else prs_ p s `shouldParse` a
 
 ----------------------------------------------------------------------------
 -- Helpers
diff --git a/tests/Control/Monad/CombinatorsSpec.hs b/tests/Control/Monad/CombinatorsSpec.hs
new file mode 100644
--- /dev/null
+++ b/tests/Control/Monad/CombinatorsSpec.hs
@@ -0,0 +1,244 @@
+{-# LANGUAGE CPP        #-}
+{-# LANGUAGE MultiWayIf #-}
+
+module Control.Monad.CombinatorsSpec (spec) where
+
+import Data.List (intersperse)
+import Data.Maybe (maybeToList, isNothing, fromJust)
+import Data.Monoid
+import Test.Hspec
+import Test.Hspec.Megaparsec
+import Test.Hspec.Megaparsec.AdHoc
+import Test.QuickCheck
+import Text.Megaparsec
+import Text.Megaparsec.Char
+
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative hiding (many, some)
+#endif
+
+spec :: Spec
+spec = do
+
+  describe "count" $ do
+    it "works" . property $ \n x' -> do
+      let x = getNonNegative x'
+          p = count n (char 'x')
+          p' = count' n n (char 'x')
+          s = replicate x 'x'
+      prs_ p s `shouldBe` prs_ p' s
+    rightOrder (count 3 letterChar) "abc" "abc"
+
+  describe "count'" $ do
+    it "works" . property $ \m n x' -> do
+      let x = getNonNegative x'
+          p = count' m n (char 'x')
+          s = replicate x 'x'
+      if | n <= 0 || m > n ->
+           if x == 0
+             then prs_ p s `shouldParse` ""
+             else prs_ p s `shouldFailWith` err posI (utok 'x' <> eeof)
+         | m <= x && x <= n ->
+           prs_ p s `shouldParse` s
+         | x < m ->
+           prs_ p s `shouldFailWith` err (posN x s) (ueof <> etok 'x')
+         | otherwise ->
+           prs_ p s `shouldFailWith` err (posN n s) (utok 'x' <> eeof)
+    rightOrder (count' 1 3 letterChar) "abc" "abc"
+
+  describe "endBy" $ do
+    it "works" . property $ \n' c -> do
+      let n = getNonNegative n'
+          p = endBy (char 'a') (char '-')
+          s = intersperse '-' (replicate n 'a') ++ [c]
+      if | c == 'a' && n == 0 ->
+           prs_ p s `shouldFailWith` err (posN (1 :: Int) s) (ueof <> etok '-')
+         | c == 'a' ->
+           prs_ p s `shouldFailWith` err (posN (g n) s) (utok 'a' <> etok '-')
+         | c == '-' && n == 0 ->
+           prs_ p s `shouldFailWith` err posI (utok '-' <> etok 'a'<> eeof)
+         | c /= '-' ->
+           prs_ p s `shouldFailWith` err (posN (g n) s)
+             ( utok c <>
+               (if n > 0 then etok '-' else eeof) <>
+               (if n == 0 then etok 'a' else mempty) )
+         | otherwise -> prs_ p s `shouldParse` replicate n 'a'
+    rightOrder (endBy letterChar (char ',')) "a,b,c," "abc"
+
+  describe "endBy1" $ do
+    it "works" . property $ \n' c -> do
+      let n = getNonNegative n'
+          p = endBy1 (char 'a') (char '-')
+          s = intersperse '-' (replicate n 'a') ++ [c]
+      if | c == 'a' && n == 0 ->
+           prs_ p s `shouldFailWith` err (posN (1 :: Int) s) (ueof <> etok '-')
+         | c == 'a' ->
+           prs_ p s `shouldFailWith` err (posN (g n) s) (utok 'a' <> etok '-')
+         | c == '-' && n == 0 ->
+           prs_ p s `shouldFailWith` err posI (utok '-' <> etok 'a')
+         | c /= '-' ->
+           prs_ p s `shouldFailWith` err (posN (g n) s)
+             ( utok c <>
+               (if n > 0 then etok '-' else mempty) <>
+               (if n == 0 then etok 'a' else mempty) )
+         | otherwise -> prs_ p s `shouldParse` replicate n 'a'
+    rightOrder (endBy1 letterChar (char ',')) "a,b,c," "abc"
+
+  describe "manyTill" $ do
+    it "works" . property $ \a' b' c' -> do
+      let [a,b,c] = getNonNegative <$> [a',b',c']
+          p = (,) <$> manyTill letterChar (char 'c') <*> many letterChar
+          s = abcRow a b c
+      if c == 0
+        then prs_ p s `shouldFailWith` err (posN (a + b) s)
+             (ueof <> etok 'c' <> elabel "letter")
+        else let (pre, post) = break (== 'c') s
+             in prs_ p s `shouldParse` (pre, drop 1 post)
+    rightOrder (manyTill letterChar (char 'd')) "abcd" "abc"
+
+  describe "someTill" $ do
+    it "works" . property $ \a' b' c' -> do
+      let [a,b,c] = getNonNegative <$> [a',b',c']
+          p = (,) <$> someTill letterChar (char 'c') <*> many letterChar
+          s = abcRow a b c
+      if | null s ->
+           prs_ p s `shouldFailWith` err posI (ueof <> elabel "letter")
+         | c == 0 ->
+           prs_ p s `shouldFailWith` err (posN (a + b) s)
+             (ueof <> etok 'c' <> elabel "letter")
+         | s == "c" ->
+           prs_ p s `shouldFailWith` err
+             (posN (1 :: Int) s) (ueof <> etok 'c' <> elabel "letter")
+         | head s == 'c' ->
+           prs_ p s `shouldParse` ("c", drop 2 s)
+         | otherwise ->
+           let (pre, post) = break (== 'c') s
+           in prs_ p s `shouldParse` (pre, drop 1 post)
+    rightOrder (someTill letterChar (char 'd')) "abcd" "abc"
+
+  describe "sepBy" $ do
+    it "works" . property $ \n' c' -> do
+      let n = getNonNegative n'
+          c = fromJust c'
+          p = sepBy (char 'a') (char '-')
+          s = intersperse '-' (replicate n 'a') ++ maybeToList c'
+      if | isNothing c' ->
+           prs_ p s `shouldParse` replicate n 'a'
+         | c == 'a' && n == 0 ->
+           prs_ p s `shouldParse` "a"
+         | n == 0 ->
+           prs_ p s `shouldFailWith` err posI
+             (utok c <> etok 'a' <> eeof)
+         | c == '-' ->
+           prs_ p s `shouldFailWith` err (posN (length s) s)
+             (ueof <> etok 'a')
+         | otherwise ->
+           prs_ p s `shouldFailWith` err (posN (g n) s)
+             (utok c <> etok '-' <> eeof)
+    rightOrder (sepBy letterChar (char ',')) "a,b,c" "abc"
+
+  describe "sepBy1" $ do
+    it "works" . property $ \n' c' -> do
+      let n = getNonNegative n'
+          c = fromJust c'
+          p = sepBy1 (char 'a') (char '-')
+          s = intersperse '-' (replicate n 'a') ++ maybeToList c'
+      if | isNothing c' && n >= 1 ->
+           prs_ p s `shouldParse` replicate n 'a'
+         | isNothing c' ->
+           prs_ p s `shouldFailWith` err posI (ueof <> etok 'a')
+         | c == 'a' && n == 0 ->
+           prs_ p s `shouldParse` "a"
+         | n == 0 ->
+           prs_ p s `shouldFailWith` err posI (utok c <> etok 'a')
+         | c == '-' ->
+           prs_ p s `shouldFailWith` err (posN (length s) s) (ueof <> etok 'a')
+         | otherwise ->
+           prs_ p s `shouldFailWith` err (posN (g n) s) (utok c <> etok '-' <> eeof)
+    rightOrder (sepBy1 letterChar (char ',')) "a,b,c" "abc"
+
+  describe "sepEndBy" $ do
+    it "works" . property $ \n' c' -> do
+      let n = getNonNegative n'
+          c = fromJust c'
+          p = sepEndBy (char 'a') (char '-')
+          a = replicate n 'a'
+          s = intersperse '-' (replicate n 'a') ++ maybeToList c'
+      if | isNothing c' ->
+           prs_ p s `shouldParse` a
+         | c == 'a' && n == 0 ->
+           prs_ p s `shouldParse` "a"
+         | n == 0 ->
+           prs_ p s `shouldFailWith` err posI (utok c <> etok 'a' <> eeof)
+         | c == '-' ->
+           prs_ p s `shouldParse` a
+         | otherwise ->
+           prs_ p s `shouldFailWith` err (posN (g n) s) (utok c <> etok '-' <> eeof)
+    rightOrder (sepEndBy letterChar (char ',')) "a,b,c," "abc"
+
+  describe "sepEndBy1" $ do
+    it "works" . property $ \n' c' -> do
+      let n = getNonNegative n'
+          c = fromJust c'
+          p = sepEndBy1 (char 'a') (char '-')
+          a = replicate n 'a'
+          s = intersperse '-' (replicate n 'a') ++ maybeToList c'
+      if | isNothing c' && n >= 1 ->
+           prs_ p s `shouldParse` a
+         | isNothing c' ->
+           prs_ p s `shouldFailWith` err posI (ueof <> etok 'a')
+         | c == 'a' && n == 0 ->
+           prs_ p s `shouldParse` "a"
+         | n == 0 ->
+           prs_ p s `shouldFailWith` err posI (utok c <> etok 'a')
+         | c == '-' ->
+           prs_ p s `shouldParse` a
+         | otherwise ->
+           prs_ p s `shouldFailWith` err (posN (g n) s) (utok c <> etok '-' <> eeof)
+    rightOrder (sepEndBy1 letterChar (char ',')) "a,b,c," "abc"
+
+  describe "skipMany" $
+    it "works" . property $ \c n' a -> do
+      let p = skipMany (char c) *> string a
+          n = getNonNegative n'
+          p' = many (char c) >> string a
+          s = replicate n c ++ a
+      prs_ p s `shouldBe` prs_ p' s
+
+  describe "skipSome" $
+    it "works" . property $ \c n' a -> do
+      let p = skipSome (char c) *> string a
+          n = getNonNegative n'
+          p' = some (char c) >> string a
+          s = replicate n c ++ a
+      prs_ p s `shouldBe` prs_ p' s
+
+  describe "skipCount" $
+    it "works" . property $ \c n' a -> do
+      let p = skipCount n (char c) *> string a
+          n = getNonNegative n'
+          p' = count n (char c) *> string a
+          s = replicate n c ++ a
+      prs_ p s `shouldBe` prs_ p' s
+
+  describe "skipManyTill" $
+    it "works" . property $ \c n' a -> c /= a ==> do
+      let p = skipManyTill (char c) (char a)
+          n = getNonNegative n'
+          s = replicate n c ++ [a]
+      prs_ p s `shouldParse` a
+
+  describe "skipSomeTill" $
+    it "works" . property $ \c n' a -> c /= a ==> do
+      let p = skipSomeTill (char c) (char a)
+          n = getNonNegative n'
+          s = replicate n c ++ [a]
+      if n == 0
+        then prs_ p s `shouldFailWith` err posI (utok a <> etok c)
+        else prs_ p s `shouldParse` a
+
+----------------------------------------------------------------------------
+-- Helpers
+
+g :: Int -> Int
+g x = x + if x > 0 then x - 1 else 0
diff --git a/tests/Test/Hspec/Megaparsec/AdHoc.hs b/tests/Test/Hspec/Megaparsec/AdHoc.hs
--- a/tests/Test/Hspec/Megaparsec/AdHoc.hs
+++ b/tests/Test/Hspec/Megaparsec/AdHoc.hs
@@ -17,6 +17,7 @@
     -- * Other
   , abcRow
   , toFirstMismatch
+  , rightOrder
   , Parser )
 where
 
@@ -169,6 +170,17 @@
   -> String            -- ^ Resulting prefix
 toFirstMismatch f str s = take (n + 1) s
   where n = length (takeWhile (uncurry f) (zip str s))
+
+-- | Check that the given parser returns the list in the right order.
+
+rightOrder
+  :: Parser String     -- ^ The parser to test
+  -> String            -- ^ Input for the parser
+  -> String            -- ^ Expected result
+  -> Spec
+rightOrder p s s' =
+  it "produces the list in the right order" $
+    prs_ p s `shouldParse` s'
 
 -- | The type of parser that consumes a 'String'.
 
diff --git a/tests/Text/Megaparsec/Char/LexerSpec.hs b/tests/Text/Megaparsec/Char/LexerSpec.hs
--- a/tests/Text/Megaparsec/Char/LexerSpec.hs
+++ b/tests/Text/Megaparsec/Char/LexerSpec.hs
@@ -6,7 +6,6 @@
 
 module Text.Megaparsec.Char.LexerSpec (spec) where
 
-import Control.Applicative
 import Control.Monad
 import Data.Char hiding (ord)
 import Data.List (isInfixOf)
@@ -22,6 +21,10 @@
 import Text.Megaparsec
 import Text.Megaparsec.Char.Lexer
 import qualified Text.Megaparsec.Char as C
+
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative hiding (many, some)
+#endif
 
 spec :: Spec
 spec = do
diff --git a/tests/Text/Megaparsec/CharSpec.hs b/tests/Text/Megaparsec/CharSpec.hs
--- a/tests/Text/Megaparsec/CharSpec.hs
+++ b/tests/Text/Megaparsec/CharSpec.hs
@@ -205,9 +205,11 @@
           prs  (char ch) "" `shouldFailWith` err posI (ueof <> etok ch)
 
   describe "char'" $ do
+    let goodChar x =
+          (toUpper x == toLower x) || (isUpper x || isLower x)
     context "when stream begins with the character specified as argument" $
       it "parses the character" $
-        property $ \ch s -> do
+        property $ \ch s -> goodChar ch ==> do
           let sl = toLower ch : s
               su = toUpper ch : s
           prs  (char' ch) sl `shouldParse`     toLower ch
@@ -216,7 +218,7 @@
           prs' (char' ch) su `succeedsLeaving` s
     context "when stream does not begin with the character specified as argument" $
       it "signals correct parse error" $
-        property $ \ch ch' s -> toLower ch /= toLower ch' ==> do
+        property $ \ch ch' s -> goodChar ch && toLower ch /= toLower ch' ==> do
           let s' = ch' : s
               ms = utok ch' <> etok (toLower ch) <> etok (toUpper ch)
           prs  (char' ch) s' `shouldFailWith` err posI ms
diff --git a/tests/Text/Megaparsec/ExprSpec.hs b/tests/Text/Megaparsec/ExprSpec.hs
--- a/tests/Text/Megaparsec/ExprSpec.hs
+++ b/tests/Text/Megaparsec/ExprSpec.hs
@@ -14,7 +14,7 @@
 import Text.Megaparsec.Expr
 
 #if !MIN_VERSION_base(4,8,0)
-import Control.Applicative
+import Control.Applicative hiding (many, some)
 #endif
 
 spec :: Spec
diff --git a/tests/Text/MegaparsecSpec.hs b/tests/Text/MegaparsecSpec.hs
--- a/tests/Text/MegaparsecSpec.hs
+++ b/tests/Text/MegaparsecSpec.hs
@@ -11,7 +11,6 @@
 
 module Text.MegaparsecSpec (spec) where
 
-import Control.Applicative
 import Control.Monad.Cont
 import Control.Monad.Except
 import Control.Monad.Identity
@@ -46,6 +45,10 @@
 import qualified Data.Text                   as T
 import qualified Data.ByteString             as BS
 
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative hiding (many, some)
+#endif
+
 #if !MIN_VERSION_QuickCheck(2,8,2)
 instance (Arbitrary a, Ord a) => Arbitrary (E.Set a) where
   arbitrary = E.fromList <$> arbitrary
@@ -1284,16 +1287,23 @@
           runParser' p st `shouldBe` (st', Right stateInput)
 
     describe "atEnd" $ do
-      let p :: Parser Bool
-          p = atEnd
-      context "when stream is empty" $
+      let p, p' :: Parser Bool
+          p  = atEnd
+          p' = p <* empty
+      context "when stream is empty" $ do
         it "returns True" $
           prs p "" `shouldParse` True
-      context "when stream is not empty" $
+        it "does not produce hints" $
+          prs p' "" `shouldFailWith` err posI mempty
+      context "when stream is not empty" $ do
         it "returns False" $
           property $ \s -> not (null s) ==> do
             prs  p s `shouldParse` False
             prs' p s `succeedsLeaving` s
+        it "does not produce hints" $
+          property $ \s -> not (null s) ==> do
+            prs  p' s `shouldFailWith` err posI mempty
+            prs' p' s `failsLeaving` s
 
   describe "combinators for manipulating parser state" $ do
 
