Product combines two values that live in the same structure. For parsers, it means: run one parser, then another; if both succeed, keep both results as a pair. A parser for A and a parser for B therefore produce a parser for (A, B). The symbolic spelling ** is an alias for product. section 9.2.1
Build a nonempty repetition
A one-or-more parser need not be primitive. First parse one p, then parse p.many, and combine the head and tail with ::. Product supplies the paired inputs; map2 transforms that pair into the desired result. This separates sequencing from the rule for combining successful values. section 9.2.1 section 9.8
This distinction is useful because product says only “keep both,” while map2 says “run both and calculate a new result.” Defining map2 through product and map makes the relationship explicit: product creates Parser[(A, B)], then map applies the combining function. The same pattern builds listOfN and separated sequences. section 9.2.1 section 9.8
Recursive parser combinators expose an operational requirement: the second parser must be accepted nonstrictly. A direct many definition recursively constructs p.many before parsing begins and can overflow the stack. Deferring that recursive parser lets product and map2 sequence each step only when it is needed. section 9.2.1 section 9.8
extension [A](p: Parser[A]) def product[B](p2: Parser[B]): Parser[(A, B)] def **[B](p2: Parser[B]): Parser[(A, B)] = product(p2) #1
The parser signature makes the result shape visible: sequencing Parser[A] with Parser[B] preserves both values in a tuple. section 9.2.1
For applicative structures, product is the general operation that combines two effects into an effect containing a pair, usually defined with map2. Its associativity law permits either grouping of three products, provided a tuple reassociation map aligns the nested pair shapes. Without that law, derived operations such as map3 would need separate left- and right-grouped variants. section 12.5.2 section 12.9
Product obeys two especially useful expectations:
- Associativity: (a ** b) ** c and a ** (b ** c) have equivalent behavior after reshaping nested pairs. section 9.8 section 12.5.2
- Naturality: mapping each component before product agrees with taking product first and mapping the pair afterward. section 9.8 section 12.9
