In this example ported to F# from Richard Bird's book, glue is supposed to take a digit and a tuple of (Expression, Values) and return a list of (Expression, Values) tuples. But there is a syntactic bug that cannot be inferred without more context (n.b. the list delimiter in F# is a semi-colon rather than comma):
type Digit = int
type Factor = Digit list
type Term = Factor list
type Expression = Term list
type Values = (Digit * Digit * Digit * Digit)
let glue x ((xs :: xss) :: xsss, (k, f, t, e)) =
[(((x :: xs) :: xss) :: xsss, (10 * k, k * x + f, t, e)),
(([x] :: xs :: xss) :: xsss, (10, x, f * t, e)),
([[x]] :: (xs :: xss) :: xsss, (10, x, 1, f * t + e))]
type Digit = int
type Factor = Digit list
type Term = Factor list
type Expression = Term list
type Values = (Digit * Digit * Digit * Digit)
let glue x ((xs :: xss) :: xsss, (k, f, t, e)) =
[(((x :: xs) :: xss) :: xsss, (10 * k, k * x + f, t, e)),
(([x] :: xs :: xss) :: xsss, (10, x, f * t, e)),
([[x]] :: (xs :: xss) :: xsss, (10, x, 1, f * t + e))]
In an IDE, the type checker makes the error obvious once annotations are added. Editing for the correct list delimiters, glue is defined as:
let glue' (x: Digit) (ev: Expression * Values) : (Expression * Values) list =
match x, ev with
| x, ((xs :: xss) :: xsss, (k, f, t, e)) ->
[(((x :: xs) :: xss) :: xsss, (10 * k, k * x + f, t, e));
(([x] :: xs :: xss) :: xsss, (10, x, f * t, e));
([[x]] :: (xs :: xss) :: xsss, (10, x, 1, f * t + e))]
Just another reminder that "explicit is better than implicit".
let glue' (x: Digit) (ev: Expression * Values) : (Expression * Values) list =
match x, ev with
| x, ((xs :: xss) :: xsss, (k, f, t, e)) ->
[(((x :: xs) :: xss) :: xsss, (10 * k, k * x + f, t, e));
(([x] :: xs :: xss) :: xsss, (10, x, f * t, e));
([[x]] :: (xs :: xss) :: xsss, (10, x, 1, f * t + e))]
Just another reminder that "explicit is better than implicit".