Ken Wakita (https://wakita.github.io/fp2018/)
Oct. 4, 2018
A record can be regarded as a tuple whose elements are accessible by names. For example a ratio record as defined below can be regarded as a pair of int’s whose elements are referenced by num and denom.
A record data constructed by the following syntax:
And names are used to access its elements:
Variant types can be used to represent a member of finite flags/sets/states/tags. At first, it may look like enum type in C-like languages. For example, the sign type denotes the domain that is either positive or negative.
Positive and Negative are called constructors of the sign type.
As we use switch syntax to identify a enum value, we use pattern matching in OCaml:
let sign_int n =
if n >= 0 then Positive
else Negative;;
Like Java’s Enum type, members of a variant type can have values. In this case, the member’s declaration contains its type: For example, the color type represents colors by several popular colors (black, white, red, …, cyan), and others that are expressed by combinations of red-, green-, blue-intensity.
type color = Black | White | Red | ... | Cyan | RGB of int * int * int;;
let colors = [Black; White; RGB(255, 0, 0); RGB(0, 255, 0); RGB(0, 0, 255)];;We use pattern matching to identify the kind of color type and its value if any.
A recursive data type can be easily defined by referencing the type name being defined in its definition. Let’s look at the definition of the 'a binary_tree type:
type 'a binary_tree =
Empty
| Node of 'a * 'a binary_tree * 'a binary_tree;;
type 'a binary_tree = Empty | Node of 'a * 'a binary_tree * 'a binary_treeIt offers two constructors: Empty represents a leaf of a tree and Node an internal node. The Node constructor contains a triple of a value of type 'a and two subtrees both of type 'a binary_tree.
Node(4, Node(2, Node(1, Empty, Empty), Node(3, Empty, Empty)), Empty)
- : int binary_tree =
Node (4, Node (2, Node (1, Empty, Empty), Node (3, Empty, Empty)), Empty)
Empty and Node, the label of the circle its value, and arrows references to subtrees.A function that manipulates of trees can simply be defined by use of pattern matching.
Constructing a recursive data while traversing another. The definition below gives a new binary tree that
valuesDefine a function named values that takes a binary tree and gives a list of values contained in the tree following the order that occur from left to right in the tree.
values Node(4, Node(2, Node(1, Empty, Empty), Node(3, Empty, Empty)), Node(5, Empty, Empty)) should give [1; 2; 3; 4; 5].
values(* This implimentation is not efficient because of
its use of the append operator (`@`).
The comptational complexity is a square of the size of the tree.
Can you guess its worst case scenario? *)
let rec values t =
match t with
| Empty -> []
| Node(x, left, right) -> values left @ [x] @ values right;;valuesmirrorDefine a function named mirror that takes a binary tree and construct a mirror image of the given tree.

mirror of the treemirroris_binary_search_treeIt is important for the binary search tree that its elements are sorted. If it is not the case the member and insert do not work as we expect: e.g. member 1 (Node(2, Empty, (Node(1, Empty, Empty)))) fails to find 1 contained in the tree.
Define a function name is_binary_search_tree that takes a tree and tells if it is a binary search tree.
is_binary_search_treelet is_binary_search_tree t =
let rec aux test t =
match t with
| Empty -> true
| Node(y, left, right) ->
test y &&
aux (function x -> test x && x < y) left &&
aux (function x -> test x && x > y) right in
aux (function _ -> true) t;;Unfortunately the computational complexity of this solution is quadratic of the tree size. Two more efficient solutions are found in the complete answers slide.
Complete answers to the exercises:
Download 03-exercise.ml
Download 03-exercise.ml
The second coding assignment will be posted tonight at OCW-i. The due date will be presented as well.