Standard ML has special syntax for products (tuples). A product type is written as

```
t1 * t2 * ... * tN
```

and a product pattern is written as

```
(p1, p2, ..., pN)
```

In most situations the syntax is quite convenient. However, there are situations where the syntax is cumbersome. There are also situations in which it is useful to construct and destruct n-ary products inductively, especially when using Fold.

In such situations, it is useful to have a binary product datatype with an infix constructor defined as follows.

```
datatype ('a, 'b) product = & of 'a * 'b
infix &
```

With these definitions, one can write an n-ary product as a nested binary product quite conveniently.

```
x1 & x2 & ... & xn
```

Because of left associativity, this is the same as

```
(((x1 & x2) & ...) & xn)
```

Because & is a constructor, the syntax can also be used for patterns.

The symbol & is inspired by the Curry-Howard isomorphism: the proof of a conjunction (A & B) is a pair of proofs (a, b).

## Example: parser combinators

A typical parser combinator library provides a combinator that has a type of the form.

```
'a parser * 'b parser -> ('a * 'b) parser
```

and produces a parser for the concatenation of two parsers. When more than two parsers are concatenated, the result of the resulting parser is a nested structure of pairs

```
(...((p1, p2), p3)..., pN)
```

which is somewhat cumbersome.

By using a product type, the type of the concatenation combinator then becomes

```
'a parser * 'b parser -> ('a, 'b) product parser
```

While this doesn’t stop the nesting, it makes the pattern significantly easier to write. Instead of

```
(...((p1, p2), p3)..., pN)
```

the pattern is written as

```
p1 & p2 & p3 & ... & pN
```

which is considerably more concise.