till' :: (MonadPlus m) => m a -> m b -> m ([a], b)
till' p end = mapFst ($ []) <$> scan (id, undefined)
  where scan (fp, e) = liftM (fp,) end `mplus` do !a <- p; scan (fp . (a:), e)
        mapFst f (x, y) = (f x, y)

-- | Strips arbitrary tags surrounded by @o@ and @c@ preserving any
-- text in between the opening tag and closing tag, except for
-- whatever matches @p@, which is then treated like a block element and
-- replaced by newlines, useful for e.g. <code> or [quote].
till' :: (MonadPlus m) => m a -> m b -> m ([a], b)
till' p end = mapFst ($ []) <$> scan (id, undefined)
  where scan (fp, e) = liftM (fp,) end `mplus` do !a <- p; scan (fp . (a:), e)
        mapFst f (x, y) = (f x, y)

-- | Strips arbitrary tags surrounded by @o@ and @c@ preserving any
-- text in between the opening tag and closing tag, except for
-- whatever matches @p@, which is then treated like a block element and
-- replaced by newlines, useful for e.g. <code> or [quote].
till' p end = mapFst ($ []) <$> scan (id, undefined)
  where scan (fp, e) = liftM (fp,) end `mplus` do !a <- p; scan (fp . (a:), e)
        mapFst f (x, y) = (f x, y)

-- | Strips arbitrary tags surrounded by @o@ and @c@ preserving any
-- text in between the opening tag and closing tag, except for
-- whatever matches @p@, which is then treated like a block element and
-- replaced by newlines, useful for e.g. <code> or [quote].