Simple Prefix Matching Library in Haskell
Library functions, particularly Maybe's Applicative/Alternative instances, can make your code more consise:

makeMatcher spec str = length spec &lt;$ guard (isPrefixOf spec str)

andThen m1 m2 str = do
  l1 &lt;- m1 str
  l2 &lt;- m2 $ drop l1 str
  Just $ l1 + l2

symOrExn m1 m2 str = case catMaybes [m1 str, m2 str] of
  [] -&gt; Nothing
  [l] -&gt; Just l
  -- if you reach this case, the grammar was
  -- constructed badly
  [_, _] -&gt; error "ambiguous match"

leftOr = liftA2 (&lt;|&gt;)

andThenList = foldr andThen identityMatcher

leftOrList = foldr leftOr identityMatcher


A more potent approach is to return not the length at which to split, but the results of the split. In fact, StateT String Maybe String makes this work out of the box:

type Matcher = StateT String Maybe String

makeMatcher :: String -&gt; Matcher
makeMatcher spec = StateT $ fmap (spec,) . stripPrefix spec

runMatcher :: Matcher -&gt; String -&gt; Maybe (String, String)
runMatcher = runStateT

andThen = liftA2 (++)

symOrExn m1 m2 = m1 &lt;* (m2 *&gt; error "ambiguous match" &lt;|&gt; pure ()) &lt;|&gt; m2
  -- I'll admit, this one looks clunky

leftOr = (&lt;|&gt;)

andThenList = fmap concat . sequenceA

leftOrList = asum