listOfN repeats a parser exactly a specified number of times and collects the parsed values in order. A parser for either "ab" or "cad", followed by listOfN(3), accepts three consecutive alternatives and returns a List[String]. The combinator is parametric: the repeated parser may produce strings, characters, or any other result type. section 9.1
Parsing exactly three alternatives
Given p = (string("ab") | string("cad")).listOfN(3), input "ababcad" produces List("ab", "ab", "cad"); "cadabab" and "ababab" also succeed with their three parsed pieces. Unlike an unbounded repetition combinator, the count is fixed before parsing begins. section 9.1 section 9.8
The recursive design mirrors the required count. For n <= 0, succeed with an empty list. Otherwise, parse one value with p, recursively parse n - 1 more values, and use map2 with cons to prepend the first result. This makes the list structure correspond directly to the sequence consumed from input. section 9.8
listOfN is closely related to many: both accumulate repeated parser results, but many stops when parsing no longer succeeds whereas listOfN has an explicit limit. Recursive repetition also exposes an evaluation concern: a strict second argument to map2 can construct recursive parsers too early, so parser combinators may make that argument nonstrict or defer it. section 9.8
The same collection pattern also appears in generators. A Gen[A].listOfN(n) creates n copies of a generator and sequences them, turning List[Gen[A]] into Gen[List[A]]. When the size itself is generated, flatMap selects the corresponding fixed-size generator after producing the size. section 8.1.4 section 8.6
