ProductType =========== <:StandardML:Standard ML> has special syntax for products (tuples). A product type is written as [source,sml] ---- t1 * t2 * ... * tN ---- and a product pattern is written as [source,sml] ---- (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. [source,sml] ---- 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. [source,sml] ---- x1 & x2 & ... & xn ---- Because of left associativity, this is the same as [source,sml] ---- (((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. [source,sml] ---- '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 [source,sml] ---- (...((p1, p2), p3)..., pN) ---- which is somewhat cumbersome. By using a product type, the type of the concatenation combinator then becomes [source,sml] ---- '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 [source,sml] ---- (...((p1, p2), p3)..., pN) ---- the pattern is written as [source,sml] ---- p1 & p2 & p3 & ... & pN ---- which is considerably more concise. == Also see == * <:VariableArityPolymorphism:> * <:Utilities:>