diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+Version 0.7.2
+---------------
+* Added `Combinators.takeSomeNonEmpty`
+* Updated CI configuration
+* Bumped the upper bounds of the `witherable` and `containers` dependencies
+* Slightly improved documentation
+
 Version 0.7.1
 ---------------
 * Added a Show instance for every Show1 to satisfy the new class declaration
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -22,9 +22,9 @@
 import qualified Rank2.TH
 ~~~
 
-What puts this library apart from most is that these parsers are *grammatical*, just as the library name says. Instead
-of writing the parser definitions as top-level bindings, you can and should group them into a grammar record definition,
-like this:
+What puts this library apart from most is that the parsers it allows you to construct are *grammatical*, just as the
+library name says. Instead of writing the parser definitions as top-level bindings, you can and should group them into
+a grammar record definition, like this:
 
 ~~~ {.haskell}
 arithmetic :: Rank2.Apply g => GrammarBuilder Arithmetic g Parser String
@@ -41,9 +41,9 @@
    number= takeCharsWhile1 isDigit <?> "number"}
 ~~~
 
-What on Earth for? One good reason is that these parser definitions can then be left-recursive, which is normally a
-death knell for parser libraries. There are other benefits like memoization and grammar composability, and the main
-downside is the obligation to declare the grammar record:
+What on Earth for? One good reason is that these parser definitions can then be left-recursive, which is usually
+deadly for parser combinator libraries. There are other benefits like memoization and grammar composability, and the
+main downside is the obligation to declare the grammar record:
 
 ~~~ {.haskell}
 data Arithmetic f = Arithmetic{sum     :: f Int,
diff --git a/examples/Combined.hs b/examples/Combined.hs
--- a/examples/Combined.hs
+++ b/examples/Combined.hs
@@ -18,6 +18,8 @@
 import qualified Conditionals
 import qualified Lambda
 
+-- | Grammar that combines arithmetic, boolean, comparison, conditional, and lambda expression grammars. The first
+-- three productions are used to bind them all together, see 'expression' below.
 data Expression f =
    Expression{
       expr :: f Domain,
@@ -29,6 +31,7 @@
       conditionalGrammar :: Conditionals.Conditionals Domain Domain f,
       lambdaGrammar :: Lambda.Lambda Domain f}
 
+-- | The combined domain result type tags different component results with their type.
 data Tagged = IntExpression {intFromExpression :: Int}
             | BoolExpression {boolFromExpression :: Bool}
             | FunctionExpression {functionFromExpression :: Tagged -> Tagged}
@@ -37,6 +40,7 @@
 
 type Env = Map String Tagged
 
+-- | The semantic domain of the parsed expression
 type Domain = Env -> Tagged
 
 instance Eq (Tagged -> Tagged) where
@@ -125,7 +129,8 @@
 instance TokenParsing (Parser Expression String)
 instance LexicalParsing (Parser Expression String)
 
-{-
+{- The Rank.TH.deriveAll splice above inserts the following declarations:
+
 instance Rank2.Functor Expression where
    f <$> g = g{expr= f (expr g),
                term= f (term g),
@@ -206,12 +211,16 @@
    in Expression{expr= combinedExpr,
                  term= combinedTerm,
                  primary= combinedPrimary,
-                 arithmeticGrammar= Arithmetic.arithmetic arithmeticGrammar{Arithmetic.expr= expr,
-                                                                            Arithmetic.primary= primary},
+                 arithmeticGrammar= Arithmetic.arithmetic arithmeticGrammar{
+                    Arithmetic.expr= expr,
+                    Arithmetic.primary= primary},
                  booleanGrammar= Boolean.boolean (Comparisons.test comparisonGrammar) booleanGrammar,
-                 comparisonGrammar= Comparisons.comparisons comparisonGrammar{Comparisons.term= Arithmetic.expr arithmeticGrammar},
-                 conditionalGrammar= Conditionals.conditionals conditionalGrammar{Conditionals.test= Boolean.expr booleanGrammar,
-                                                                                  Conditionals.term= expr},
-                 lambdaGrammar= Lambda.lambdaCalculus lambdaGrammar{Lambda.expr= expr,
-                                                                    Lambda.application= term,
-                                                                    Lambda.primary= primary}}
+                 comparisonGrammar= Comparisons.comparisons comparisonGrammar{
+                    Comparisons.term= Arithmetic.expr arithmeticGrammar},
+                 conditionalGrammar= Conditionals.conditionals conditionalGrammar{
+                    Conditionals.test= Boolean.expr booleanGrammar,
+                    Conditionals.term= expr},
+                 lambdaGrammar= Lambda.lambdaCalculus lambdaGrammar{
+                    Lambda.expr= expr,
+                    Lambda.application= term,
+                    Lambda.primary= primary}}
diff --git a/grammatical-parsers.cabal b/grammatical-parsers.cabal
--- a/grammatical-parsers.cabal
+++ b/grammatical-parsers.cabal
@@ -1,5 +1,5 @@
 name:                grammatical-parsers
-version:             0.7.1
+version:             0.7.2
 synopsis:            parsers that combine into grammars
 description:
   /Gram/matical-/pa/rsers, or Grampa for short, is a library of parser types whose values are meant to be assigned
@@ -16,7 +16,7 @@
 category:            Text, Parsing
 build-type:          Custom
 cabal-version:       >=1.10
-tested-with:         GHC==9.2.2, GHC==9.0.2, GHC==8.10.4, GHC==8.8.4, GHC==8.6.5, GHC==8.4.4, GHC==8.2.2
+tested-with:         GHC==9.8.2, GHC==9.6.4, GHC==9.4.8, GHC==9.2.8, GHC==9.0.2, GHC==8.10.7
 extra-source-files:  README.md, CHANGELOG.md
 source-repository head
   type:              git
@@ -49,13 +49,13 @@
   default-language:    Haskell2010
   ghc-options:         -Wall
   build-depends:       base >=4.9 && <5,
-                       containers >= 0.4 && < 0.7,
+                       containers >= 0.4 && < 0.8,
                        transformers >= 0.5 && < 0.7,
                        monoid-subclasses >=1.0 && <1.3,
                        parsers < 0.13,
                        input-parsers < 0.4,
                        attoparsec >= 0.13 && < 0.15,
-                       witherable == 0.4.*,
+                       witherable >= 0.4 && < 0.6,
                        rank2classes >= 1.4.6 && < 1.6
 
 executable             arithmetic
@@ -63,7 +63,7 @@
   main-is:             Main.hs
   other-modules:       Arithmetic, Boolean, Combined, Comparisons, Conditionals, Lambda, Utilities
   default-language:    Haskell2010
-  build-depends:       base >=4.9 && <5, containers >= 0.5.7.0 && < 0.7,
+  build-depends:       base >=4.9 && <5, containers >= 0.5.7.0 && < 0.8,
                        parsers < 0.13,
                        rank2classes >= 1.0.2 && < 1.6, grammatical-parsers,
                        monoid-subclasses
@@ -73,7 +73,7 @@
   main-is:             BooleanTransformations.hs
   other-modules:       Boolean, Utilities
   default-language:    Haskell2010
-  build-depends:       base >=4.9 && <5, containers >= 0.5.7.0 && < 0.7,
+  build-depends:       base >=4.9 && <5, containers >= 0.5.7.0 && < 0.8,
                        parsers < 0.13,
                        rank2classes >= 1.0.2 && < 1.6, grammatical-parsers,
                        monoid-subclasses
@@ -82,9 +82,9 @@
   type:              exitcode-stdio-1.0
   hs-source-dirs:    test, examples
   x-uses-tf:         true
-  build-depends:     base >=4.9 && < 5, containers >= 0.5.7.0 && < 0.7,
+  build-depends:     base >=4.9 && < 5, containers >= 0.5.7.0 && < 0.8,
                      monoid-subclasses, parsers < 0.13,
-                     witherable == 0.4.*,
+                     witherable >= 0.4 && < 0.6,
                      rank2classes >= 1.0.2 && < 1.6, grammatical-parsers,
                      QuickCheck >= 2 && < 3, checkers >= 0.4.6 && < 0.6,
                      tasty >= 0.7, tasty-quickcheck >= 0.7
@@ -109,7 +109,7 @@
   ghc-options:       -O2 -Wall -rtsopts -main-is Benchmark.main
   Build-Depends:     base >=4.9 && < 5, rank2classes >= 1.0.2 && < 1.6, grammatical-parsers,
                      monoid-subclasses, parsers < 0.13,
-                     criterion >= 1.0, deepseq >= 1.1, containers >= 0.5.7.0 && < 0.7, text >= 1.1
+                     criterion >= 1.0, deepseq >= 1.1, containers >= 0.5.7.0 && < 0.8, text >= 1.1
   main-is:           Benchmark.hs
   other-modules:     Main, Arithmetic, Boolean, Combined, Comparisons, Conditionals, Lambda, Utilities
   default-language:  Haskell2010
diff --git a/src/Text/Grampa.hs b/src/Text/Grampa.hs
--- a/src/Text/Grampa.hs
+++ b/src/Text/Grampa.hs
@@ -50,12 +50,14 @@
 
 import Prelude hiding (drop, null)
 
--- | Fixed grammar record type @g@ with a given parser type @p@ on input streams of type @s@
+-- | A grammar is a record type @g@ whose fields are parsers of type @p@ on input streams of type @s@. A value of a
+-- @Grammar@ type is typically produced by applying 'fixGrammar' or 'overlay' to a 'GrammarBuilder'.
 type Grammar (g  :: (Type -> Type) -> Type) p s = g (p g s)
 
--- | A @GrammarBuilder g g' p s@ is an endomorphic function on a grammar @g@, whose parsers of type @p@ build grammars
--- of type @g'@, parsing input streams of type @s@. The first grammar @g@ may be a building block for the final
--- grammar @g'@.
+-- | A @GrammarBuilder g g' p s@ is an endomorphic function on a grammar @g@, whose parsers of type @p@ build on
+-- grammars of type @g'@ and parse an input stream of type @s@. Grammar parameters @g@ and @g'@ are typically
+-- identical in simple monolithic grammars, but when composing complex grammars the first grammar parameter @g@ would
+-- be just a building block for the final grammar @g'@.
 type GrammarBuilder (g  :: (Type -> Type) -> Type)
                     (g' :: (Type -> Type) -> Type)
                     (p  :: ((Type -> Type) -> Type) -> Type -> Type -> Type)
diff --git a/src/Text/Grampa/Class.hs b/src/Text/Grampa/Class.hs
--- a/src/Text/Grampa/Class.hs
+++ b/src/Text/Grampa/Class.hs
@@ -35,6 +35,7 @@
 
 import Prelude hiding (takeWhile)
 
+-- | A parse results in either a 'ParseFailure' or the result of the appropriate type.
 type ParseResults s = Either (ParseFailure Pos s)
 
 -- | A 'ParseFailure' contains the offset of the parse failure and the list of things expected at that offset.
diff --git a/src/Text/Grampa/Combinators.hs b/src/Text/Grampa/Combinators.hs
--- a/src/Text/Grampa/Combinators.hs
+++ b/src/Text/Grampa/Combinators.hs
@@ -1,6 +1,6 @@
 {-# LANGUAGE TypeFamilies, TypeOperators #-}
 -- | A collection of useful parsing combinators not found in dependent libraries.
-module Text.Grampa.Combinators (moptional, concatMany, concatSome, someNonEmpty,
+module Text.Grampa.Combinators (moptional, concatMany, concatSome, someNonEmpty, takeSomeNonEmpty,
                                 flag, count, upto,
                                 delimiter, operator, keyword) where
 
@@ -11,7 +11,8 @@
 import Data.Semigroup (Semigroup(sconcat))
 import Data.Semigroup.Cancellative (LeftReductive)
 
-import Text.Grampa.Class (InputParsing(ParserInput, string), LexicalParsing(lexicalToken, keyword))
+import Text.Grampa.Class (InputParsing(ParserInput, string), LexicalParsing(lexicalToken, keyword),
+                          DeterministicParsing(takeMany))
 import Text.Parser.Combinators (Parsing((<?>)), count)
 
 -- | Attempts to parse a monoidal value, if the argument parser fails returns 'mempty'.
@@ -29,6 +30,10 @@
 -- | One or more argument occurrences like 'some', returned in a 'NonEmpty' list.
 someNonEmpty :: Alternative p => p a -> p (NonEmpty a)
 someNonEmpty p = (:|) <$> p <*> many p
+
+-- | The longest sequence of One or more argument occurrences like 'takeSome', returned in a 'NonEmpty' list.
+takeSomeNonEmpty :: DeterministicParsing p => p a -> p (NonEmpty a)
+takeSomeNonEmpty p = (:|) <$> p <*> takeMany p
 
 -- | Returns 'True' if the argument parser succeeds and 'False' otherwise.
 flag :: Alternative p => p a -> p Bool
diff --git a/src/Text/Grampa/Internal.hs b/src/Text/Grampa/Internal.hs
--- a/src/Text/Grampa/Internal.hs
+++ b/src/Text/Grampa/Internal.hs
@@ -181,8 +181,11 @@
    failureOf (ResultList _ failure) = failure
    failWith = ResultList []
 
+-- | The class of parsers whose execution can be traced for debugging purposes
 class InputParsing m => TraceableParsing m where
+   -- | Modify the argument parser to log its input whenever invoked.
    traceInput :: (ParserInput m -> String) -> m a -> m a
+   -- | Modify the argument parser to log the given description and its input whenever invoked.
    traceAs :: Show (ParserInput m) => String -> m a -> m a
    traceAs description = traceInput (\input-> description <> " @ " <> show input)
 
diff --git a/test/README.lhs b/test/README.lhs
--- a/test/README.lhs
+++ b/test/README.lhs
@@ -22,9 +22,9 @@
 import qualified Rank2.TH
 ~~~
 
-What puts this library apart from most is that these parsers are *grammatical*, just as the library name says. Instead
-of writing the parser definitions as top-level bindings, you can and should group them into a grammar record definition,
-like this:
+What puts this library apart from most is that the parsers it allows you to construct are *grammatical*, just as the
+library name says. Instead of writing the parser definitions as top-level bindings, you can and should group them into
+a grammar record definition, like this:
 
 ~~~ {.haskell}
 arithmetic :: Rank2.Apply g => GrammarBuilder Arithmetic g Parser String
@@ -41,9 +41,9 @@
    number= takeCharsWhile1 isDigit <?> "number"}
 ~~~
 
-What on Earth for? One good reason is that these parser definitions can then be left-recursive, which is normally a
-death knell for parser libraries. There are other benefits like memoization and grammar composability, and the main
-downside is the obligation to declare the grammar record:
+What on Earth for? One good reason is that these parser definitions can then be left-recursive, which is usually
+deadly for parser combinator libraries. There are other benefits like memoization and grammar composability, and the
+main downside is the obligation to declare the grammar record:
 
 ~~~ {.haskell}
 data Arithmetic f = Arithmetic{sum     :: f Int,
