Lecture 005

Data Type

unit

() : unit

Standard Data Type

bool

true : bool
false : bool

Declaring a Data Type

Enumeration Type

datatype order = LESS | EQUAL | GREATER

Every datatype is a fresh definition LESS is a constructor that takes 0 argument LESS is a value that can be used as pattern (not all value can be used as pattern)

after declaring, those variables (LESS, EQUAL, GREATER) will be stuck on type order. if we do val LESS = 12 then there is a type error.

case Int.compare (x, y) of
    LESS = ...
  | EQUAL = ...
  | GREATER = ...

Note that order is a built-in data type Int.compare : int * int -> order String.compare : string * string -> order

Infinite Type

datatype extint = NegInfo | Finite of int | PosInf
(* minList int list -> extint *)
fun minList ([]: int list) extint = PosInf
  | minList (x :: xs) = (case minList xs of
    PosInf => Finite(x)
    | Finite (y : int) => Finite(Int.mine(x, y))
    | NegInf => ... raise exception

normally this Finite x is a function application, but when Finite is a constructor, Finite 0 is a value, therefore can be used in mapping

so the type extint

type: extint
Finite: int -> extint
PosInf: extint

Recursive Type

datatype tree = Empty | Node of tree * int * tree

fun depth (Empty : tree) : int = 0
  | depth (Node (left, _, right)) = 1 + Int.max(depth left, depth right)

Theorem: for any value t : tree, depth T returns a value (depth is total) Proof: By structural induction on T Base Case: T = Empty WTS: depth Empty returns a value depth Empty => 0 (1st clause of depth) Induction Case: T = Node (l, x, r) for some value l, x, r IH: depth (l) |-> v_l (for some v_l : int) and depth (r) |-> v_r (for some v_r : int) WTS: depth (Node (l, x, r)) returns to a value depth (Node (l, x, r)) => 1 + Int.max(depth l, depth r) (2nd clause) => 1 + Int.max(v_l, depth r) (IH:1) => 1 + Int.max(v_l, v_r) (IH: 2) => some value (by math, since Int.max is total and addition is total)

datatype tree = Leaf of int | Node of tree * tree

(* flatten: tree -> int list *)
fun flatten (Leaf x : tree) : int list = [x]
  | flatten (Node (l, r)) = flatten l @ flatten r

Don't use append, that's bad. because we will add each element in the left to right list

(* flatten2: tree -> int list*)
REQUIRES: true
ENSURES: flatten2 (T, acc) = flatten (T) @ acc

fun flatten2 (Leaf x : tree, acc : int list) : int list = x :: acc
  | flatten2 (Node (l, r), acc) = flatten (l, flatten2(r, acc))

In this case above, IT IS NOT A TAIL RECURSIVE CALL

Table of Content