Bounded package:turtle

Apply the given pattern a number of times restricted by given lower and upper bounds, collecting the results
>>> match (bounded 2 5 "cat") "catcatcat"
[["cat","cat","cat"]]

>>> match (bounded 2 5 "cat") "cat"
[]

>>> match (bounded 2 5 "cat") "catcatcatcatcatcat"
[]
bounded could be implemented naively as follows:
bounded m n p = do
x <- choice (map pure [m..n])
count x p
Apply the given pattern at least the given number of times, collecting the results
>>> match (lowerBounded 5 dot) "123"
[]

>>> match (lowerBounded 2 dot) "123"
["123"]
Apply the given pattern 0 or more times, up to a given bound, collecting the results
>>> match (upperBounded 5 dot) "123"
["123"]

>>> match (upperBounded 2 dot) "123"
[]

>>> match ((,) <$> upperBounded 2 dot <*> chars) "123"
[("12","3"),("1","23")]