Programming Languages and Compilers CS 421 9 and

  • Slides: 88
Download presentation
Programming Languages and Compilers (CS 421) #9 and #10: Algebraic datatypes; disjoint union types,

Programming Languages and Compilers (CS 421) #9 and #10: Algebraic datatypes; disjoint union types, product types, recursive datatypes Madhusudan Parthasarathy http: //courses. engr. illinois. edu/cs 421 Based on slides by Elsa Gunter, which in turn is partly based on slides by Mattox Beckman, as updated by Vikram Adve and Gul Agha 9/17/2020 1

Midterm n Midterm from Oct 2 – Oct 4 CBTF n Topics: All topics

Midterm n Midterm from Oct 2 – Oct 4 CBTF n Topics: All topics covered till Thu Sep 20, which includes writing functions in CPS form n n n Mostly all that you have done (WAs, MPs, MLs), but will include extra questions More details on Piazza soon, including practice exam. 9/17/2020 2

Midterm Studying for this exam n n Understand the lecture slides and discussions thoroughly.

Midterm Studying for this exam n n Understand the lecture slides and discussions thoroughly. Revisit the MPs, MLs and WAs and make sure you understand the solutions thoroughly. Repeat any you are not comfortable with. Take the pdf sample exam as a thorough overview for the actual exam. Take the Prairie. Learn Midterm 1 Practice to be familiar with the precise nature of the questions and to see where you may have trouble taking the test in a timely enough manner. 9/17/2020 3

Midterm Syllabus: First 8 lectures (till Sep 20); all videos are online at echo

Midterm Syllabus: First 8 lectures (till Sep 20); all videos are online at echo 360. org; slides are up to date Basic OCaml n n n Know the basic constructs (e. g. , match, fun, let rec) like the back of your hand. Be able to determine the type of OCaml expressions Be able to evaluate OCaml expressions, both intuitively, and step by step followong the steps discussed in class Be able to describe the environment that results from a sequence of declarations Be able to describe the closure that is the result of evalutating a function declaration Understand what effect sequencing, function application and lambda lifting has on the order of evaluation of expressions 9/17/2020 4

Midterm Recursion n n Be able to write recursive functions, including (but not necessarily

Midterm Recursion n n Be able to write recursive functions, including (but not necessarily limited to) tail -recursive or forward recursive. Be able to recognize whether a function is tail-recursive, and when a recursive call is in tail call position Higher Order Functions (HOFs) n Be able to write the definitions of the common HOFs. n Be able to use map and fold to implement other functions, as in ML 2. n Be able to write functions that use other functions as arguments n Continuations and Continuation Passing Style n Understand what the basic idea of what a continuation is. n Be able rewrite an operation / procedure in direct style to take a continuation to which to pass its results, while preserving the order of evaluation. n Be able to put a complex, possibly recursive procedure into full continutation passing style, while preserving the order of evaluation. 5

Data type in Ocaml: lists n n Frequently used lists in recursive program Matched

Data type in Ocaml: lists n n Frequently used lists in recursive program Matched over two structural cases n n [ ] - the empty list (x : : xs) a non-empty list Covers all possible lists type ‘a list = [ ] | (: : ) of ‘a * ‘a list n Not quite legitimate declaration because of special syntax 9/17/2020 6

Variants - Syntax (slightly simplified) n n n type name = C 1 [of

Variants - Syntax (slightly simplified) n n n type name = C 1 [of ty 1] |. . . | Cn [of tyn] Introduce a type called name (fun x -> Ci x) : ty 1 -> name Ci is called a constructor; if the optional type argument is omitted, it is called a constant Constructors are the basis of almost all pattern matching 9/17/2020 7

Enumeration Types as Variants An enumeration type is a collection of distinct values In

Enumeration Types as Variants An enumeration type is a collection of distinct values In C and Ocaml they have an order structure; order by order of input 9/17/2020 8

Enumeration Types as Variants # type weekday = Monday | Tuesday | Wednesday |

Enumeration Types as Variants # type weekday = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday; ; type weekday = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday 9/17/2020 9

Functions over Enumerations # let day_after day = match day with Monday -> Tuesday

Functions over Enumerations # let day_after day = match day with Monday -> Tuesday | Tuesday -> Wednesday | Wednesday -> Thursday | Thursday -> Friday | Friday -> Saturday | Saturday -> Sunday | Sunday -> Monday; ; val day_after : weekday -> weekday = <fun> 9/17/2020 10

Functions over Enumerations # let rec days_later n day = match n with 0

Functions over Enumerations # let rec days_later n day = match n with 0 -> day | _ -> if n > 0 then day_after (days_later (n - 1) day) else days_later (n + 7) day; ; val days_later : int -> weekday = <fun> 9/17/2020 11

Functions over Enumerations # days_later 2 Tuesday; ; - : weekday = Thursday #

Functions over Enumerations # days_later 2 Tuesday; ; - : weekday = Thursday # days_later (-1) Wednesday; ; - : weekday = Tuesday # days_later (-4) Monday; ; - : weekday = Thursday 9/17/2020 12

Problem: # type weekday = Monday | Tuesday | Wednesday | Thursday | Friday

Problem: # type weekday = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday; ; n Write function is_weekend : weekday -> bool let is_weekend day = 9/17/2020 13

Problem: # type weekday = Monday | Tuesday | Wednesday | Thursday | Friday

Problem: # type weekday = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday; ; n Write function is_weekend : weekday -> bool let is_weekend day = match day with Saturday -> true | Sunday -> true | _ -> false 9/17/2020 14

Example Enumeration Types # type bin_op = Int. Plus. Op | Int. Minus. Op

Example Enumeration Types # type bin_op = Int. Plus. Op | Int. Minus. Op | Eq. Op | Comma. Op | Cons. Op # type mon_op = Hd. Op | Tl. Op | Fst. Op | Snd. Op 9/17/2020 15

Disjoint Union Types n Disjoint union of types, with some possibly occurring more than

Disjoint Union Types n Disjoint union of types, with some possibly occurring more than once ty 1 n ty 2 ty 1 We can also add in some new singleton elements 9/17/2020 16

Disjoint Union Types # type id = Drivers. License of int | Social. Security

Disjoint Union Types # type id = Drivers. License of int | Social. Security of int | Name of string; ; type id = Drivers. License of int | Social. Security of int | Name of string # let check_id id = match id with Drivers. License num -> not (List. mem num [13570; 99999]) | Social. Security num -> num < 90000 | Name str -> not (str = "John Doe"); ; val check_id : id -> bool = <fun> 9/17/2020 17

Problem n Create a type to represent the currencies for US, UK, Europe and

Problem n Create a type to represent the currencies for US, UK, Europe and Japan 9/17/2020 18

Problem Create a type to represent the currencies for US, UK, Europe and Japan

Problem Create a type to represent the currencies for US, UK, Europe and Japan type currency = Dollar of int | Pound of int | Euro of int | Yen of int n 9/17/2020 19

Example Disjoint Union Type # type const = Bool. Const of bool | Int.

Example Disjoint Union Type # type const = Bool. Const of bool | Int. Const of int | Float. Const of float | String. Const of string | Nil. Const | Unit. Const 9/17/2020 20

Example Disjoint Union Type # type const = Bool. Const of bool | Int.

Example Disjoint Union Type # type const = Bool. Const of bool | Int. Const of int | Float. Const of float | String. Const of string | Nil. Const | Unit. Const How to represent 7 as a const? n. Answer: Int. Const 7 n 9/17/2020 21

Polymorphism in Variants n The type 'a option is gives us something to represent

Polymorphism in Variants n The type 'a option is gives us something to represent non-existence or failure # type 'a option = Some of 'a | None; ; type 'a option = Some of 'a | None n n Used to encode partial functions Often can replace the raising of an exception 9/17/2020 22

Functions producing option # let rec first p list = match list with [

Functions producing option # let rec first p list = match list with [ ] -> None | (x: : xs) -> if p x then Some x else first p xs; ; val first : ('a -> bool) -> 'a list -> 'a option = <fun> # first (fun x -> x > 3) [1; 3; 4; 2; 5]; ; - : int option = Some 4 # first (fun x -> x > 5) [1; 3; 4; 2; 5]; ; - : int option = None 9/17/2020 23

Functions over option # let result_ok r = match r with None -> false

Functions over option # let result_ok r = match r with None -> false | Some _ -> true; ; val result_ok : 'a option -> bool = <fun> # result_ok (first (fun x -> x > 3) [1; 3; 4; 2; 5]); ; - : bool = true # result_ok (first (fun x -> x > 5) [1; 3; 4; 2; 5]); ; - : bool = false 9/17/2020 24

Problem n Write a hd and tl on lists that doesn’t raise an exception

Problem n Write a hd and tl on lists that doesn’t raise an exception and works at all types of lists. 9/17/2020 25

Problem n Write a hd and tl on lists that doesn’t raise an exception

Problem n Write a hd and tl on lists that doesn’t raise an exception and works at all types of lists. let hd list = match list with [] -> None | (x: : xs) -> Some x n let tl list = match list with [] -> None | (x: : xs) -> Some xs n 9/17/2020 26

Mapping over Variants # let option. Map f opt = match opt with None

Mapping over Variants # let option. Map f opt = match opt with None -> None | Some x -> Some (f x); ; val option. Map : ('a -> 'b) -> 'a option -> 'b option = <fun> # option. Map (fun x -> x - 2) (first (fun x -> x > 3) [1; 3; 4; 2; 5]); ; - : int option = Some 2 9/17/2020 27

Folding over Variants # let option. Fold some. Fun none. Val opt = match

Folding over Variants # let option. Fold some. Fun none. Val opt = match opt with None -> none. Val | Some x -> some. Fun x; ; val option. Fold : ('a -> 'b) -> 'b -> 'a option -> 'b = <fun> # let option. Map f opt = option. Fold (fun x -> Some (f x)) None opt; ; val option. Map : ('a -> 'b) -> 'a option -> 'b option = <fun> 9/17/2020 28

Thinking of disjoint union types 9/17/2020 29

Thinking of disjoint union types 9/17/2020 29

Recursive Types n The type being defined may be a component of itself ty

Recursive Types n The type being defined may be a component of itself ty 9/17/2020 ty’ ty 30

Recursive Data Types # type int_Bin_Tree = Leaf of int | Node of (int_Bin_Tree

Recursive Data Types # type int_Bin_Tree = Leaf of int | Node of (int_Bin_Tree * int_Bin_Tree); ; type int_Bin_Tree = Leaf of int | Node of (int_Bin_Tree * int_Bin_Tree) 9/17/2020 31

Recursive Data Type Values # let bin_tree = Node(Leaf 3, Leaf 6), Leaf (-7));

Recursive Data Type Values # let bin_tree = Node(Leaf 3, Leaf 6), Leaf (-7)); ; val bin_tree : int_Bin_Tree = Node (Leaf 3, Leaf 6), Leaf (-7)) 9/17/2020 32

Recursive Data Type Values bin_tree = Node Leaf (-7) Leaf 3 Leaf 6 9/17/2020

Recursive Data Type Values bin_tree = Node Leaf (-7) Leaf 3 Leaf 6 9/17/2020 33

Thinking of disjoint union types 9/17/2020 34

Thinking of disjoint union types 9/17/2020 34

Recursive Data Types # type exp = Var. Exp of string | Const. Exp

Recursive Data Types # type exp = Var. Exp of string | Const. Exp of const | Mon. Op. App. Exp of mon_op * exp | Bin. Op. App. Exp of bin_op * exp | If. Exp of exp* exp | App. Exp of exp * exp | Fun. Exp of string * exp 9/17/2020 35

Thinking of disjoint union types 9/17/2020 36

Thinking of disjoint union types 9/17/2020 36

Symbolic expressions as a recursive data type 9/17/2020 37

Symbolic expressions as a recursive data type 9/17/2020 37

Recursive Data Types # type bin_op = Int. Plus. Op | Int. Minus. Op

Recursive Data Types # type bin_op = Int. Plus. Op | Int. Minus. Op | Eq. Op | Comma. Op | Cons. Op | … # type const = Bool. Const of bool | Int. Const of int | … # type exp = Var. Exp of string | Const. Exp of const | Bin. Op. App. Exp of bin_op * exp | … n How to represent 6 as an exp? 9/17/2020 38

Recursive Data Types # type bin_op = Int. Plus. Op | Int. Minus. Op

Recursive Data Types # type bin_op = Int. Plus. Op | Int. Minus. Op | Eq. Op | Comma. Op | Cons. Op | … # type const = Bool. Const of bool | Int. Const of int | … # type exp = Var. Exp of string | Const. Exp of const | Bin. Op. App. Exp of bin_op * exp | … How to represent 6 as an exp? n. Answer: Const. Exp (Int. Const 6) n 9/17/2020 39

Recursive Data Types # type bin_op = Int. Plus. Op | Int. Minus. Op

Recursive Data Types # type bin_op = Int. Plus. Op | Int. Minus. Op | Eq. Op | Comma. Op | Cons. Op | … # type const = Bool. Const of bool | Int. Const of int | … # type exp = Var. Exp of string | Const. Exp of const | Bin. Op. App. Exp of bin_op * exp | … n How to represent (6, 3) as an exp? 9/17/2020 40

Recursive Data Types # type bin_op = Int. Plus. Op | Int. Minus. Op

Recursive Data Types # type bin_op = Int. Plus. Op | Int. Minus. Op | Eq. Op | Comma. Op | Cons. Op | … # type const = Bool. Const of bool | Int. Const of int | … # type exp = Var. Exp of string | Const. Exp of const | Bin. Op. App. Exp of bin_op * exp | … How to represent (6, 3) as an exp? n. Bin. Op. App. Exp (Comma. Op, Const. Exp (Int. Const 6), Const. Exp (Int. Const 3)) n 9/17/2020 41

Recursive Data Types # type bin_op = Int. Plus. Op | Int. Minus. Op

Recursive Data Types # type bin_op = Int. Plus. Op | Int. Minus. Op | Eq. Op | Comma. Op | Cons. Op | … # type const = Bool. Const of bool | Int. Const of int | … # type exp = Var. Exp of string | Const. Exp of const | Bin. Op. App. Exp of bin_op * exp | … n. How to represent [(6, 3)] as an exp? n. Bin. Op. App. Exp (Cons. Op, Bin. Op. App. Exp (Comma. Op, Const. Exp (Int. Const 6), Const. Exp (Int. Const 3)), Const. Exp Nil. Const)))); ; 9/17/2020 42

Recursive Data Types # type int_Bin_Tree = Leaf of int | Node of (int_Bin_Tree

Recursive Data Types # type int_Bin_Tree = Leaf of int | Node of (int_Bin_Tree * int_Bin_Tree); ; type int_Bin_Tree = Leaf of int | Node of (int_Bin_Tree * int_Bin_Tree) # let bin_tree = Node(Leaf 3, Leaf 6), Leaf (-7)); ; val bin_tree : int_Bin_Tree = Node (Leaf 3, Leaf 6), Leaf (-7)) 9/17/2020 43

Recursive Functions type int_Bin_Tree =Leaf of int | Node of (int_Bin_Tree * int_Bin_Tree); ;

Recursive Functions type int_Bin_Tree =Leaf of int | Node of (int_Bin_Tree * int_Bin_Tree); ; # let rec first_leaf_value tree = 9/17/2020 44

Recursive Functions # let rec first_leaf_value tree = match tree with (Leaf n) ->

Recursive Functions # let rec first_leaf_value tree = match tree with (Leaf n) -> n | Node (left_tree, right_tree) -> first_leaf_value left_tree; ; val first_leaf_value : int_Bin_Tree -> int = <fun> # let left = first_leaf_value bin_tree; ; val left : int = 3 9/17/2020 45

Problem type int_Bin_Tree =Leaf of int | Node of (int_Bin_Tree * int_Bin_Tree); ; n

Problem type int_Bin_Tree =Leaf of int | Node of (int_Bin_Tree * int_Bin_Tree); ; n Write sum_tree : int_Bin_Tree -> int n Adds all ints in tree let rec sum_tree t = 9/17/2020 46

Problem type int_Bin_Tree =Leaf of int | Node of (int_Bin_Tree * int_Bin_Tree); ; n

Problem type int_Bin_Tree =Leaf of int | Node of (int_Bin_Tree * int_Bin_Tree); ; n Write sum_tree : int_Bin_Tree -> int n Adds all ints in tree let rec sum_tree t = match t with Leaf n -> n | Node(t 1, t 2) -> sum_tree t 1 + sum_tree t 2 9/17/2020 47

Recursion over Recursive Data Types # type exp = Var. Exp of string |

Recursion over Recursive Data Types # type exp = Var. Exp of string | Const. Exp of const | Bin. Op. App. Exp of bin_op * exp | Fun. Exp of string * exp | App. Exp of exp * exp n How to count the number of occurrences of variables in an exp? 9/17/2020 48

Recursion over Recursive Data Types # type exp = Var. Exp of string |

Recursion over Recursive Data Types # type exp = Var. Exp of string | Const. Exp of const | Bin. Op. App. Exp of bin_op * exp | Fun. Exp of string * exp | App. Exp of exp * exp n Count the number of occurrences of variables in an exp? # let rec var. Cnt exp = match exp with Var. Exp x -> | Const. Exp c -> | Bin. Op. App. Exp (b, e 1, e 2) -> | Fun. Exp (x, e) -> | App. Exp (e 1, e 2) -> 9/17/2020 49

Recursion over Recursive Data Types # type exp = Var. Exp of string |

Recursion over Recursive Data Types # type exp = Var. Exp of string | Const. Exp of const | Bin. Op. App. Exp of bin_op * exp | Fun. Exp of string * exp | App. Exp of exp * exp n Count the number of occurrences of variables in an exp # let rec var. Cnt exp = match exp with Var. Exp x -> 1 | Const. Exp c -> 0 | Bin. Op. App. Exp (b, e 1, e 2) -> var. Cnt e 1 + var. Cnt e 2 | Fun. Exp (x, e) -> 1 + var. Cnt e | App. Exp (e 1, e 2) -> var. Cnt e 1 + var. Cnt e 2 9/17/2020 50

Mapping over Recursive Types # let rec ibtree. Map f tree = match tree

Mapping over Recursive Types # let rec ibtree. Map f tree = match tree with (Leaf n) -> | Node (left_tree, right_tree) -> 9/17/2020 51

Mapping over Recursive Types # let rec ibtree. Map f tree = match tree

Mapping over Recursive Types # let rec ibtree. Map f tree = match tree with (Leaf n) -> Leaf (f n) | Node (left_tree, right_tree) -> Node (ibtree. Map f left_tree, ibtree. Map f right_tree); ; val ibtree. Map : (int -> int) -> int_Bin_Tree = <fun> 9/17/2020 52

Mapping over Recursive Types # ibtree. Map ((+) 2) bin_tree; ; - : int_Bin_Tree

Mapping over Recursive Types # ibtree. Map ((+) 2) bin_tree; ; - : int_Bin_Tree = Node (Leaf 5, Leaf 8), Leaf (-5)) 9/17/2020 53

Folding over Recursive Types # let rec ibtree. Fold. Right leaf. Fun node. Fun

Folding over Recursive Types # let rec ibtree. Fold. Right leaf. Fun node. Fun tree = match tree with Leaf n -> leaf. Fun n | Node (left_tree, right_tree) -> node. Fun (ibtree. Fold. Right leaf. Fun node. Fun left_tree) (ibtree. Fold. Right leaf. Fun node. Fun right_tree); ; val ibtree. Fold. Right : (int -> 'a) -> ('a -> 'a) -> int_Bin_Tree -> 'a = <fun> 9/17/2020 54

Folding over Recursive Types # let tree_sum = ibtree. Fold. Right (fun x ->

Folding over Recursive Types # let tree_sum = ibtree. Fold. Right (fun x -> x) (+); ; val tree_sum : int_Bin_Tree -> int = <fun> # tree_sum bin_tree; ; - : int = 2 9/17/2020 55

Mutually Recursive Types Type T 1’s definition has type T 2 Type T 2’s

Mutually Recursive Types Type T 1’s definition has type T 2 Type T 2’s definition has type T 1 Example: directed trees with arbitrary arity 9/17/2020 56

Mutually Recursive Types - Values Type T 1’s definition has type T 2 Type

Mutually Recursive Types - Values Type T 1’s definition has type T 2 Type T 2’s definition has type T 1 Example: directed trees with arbitrary arity 5 7 3 2 9/17/2020 57

Mutually Recursive Types # type 'a tree = Tree. Leaf of 'a | Tree.

Mutually Recursive Types # type 'a tree = Tree. Leaf of 'a | Tree. Node of 'a tree. List and 'a tree. List = Last of 'a tree | More of ('a tree * 'a tree. List); ; type 'a tree = Tree. Leaf of 'a | Tree. Node of 'a tree. List and 'a tree. List = Last of 'a tree | More of ('a tree * 'a tree. List) 9/17/2020 58

Mutually Recursive Types - Values # let tree = Tree. Node (More (Tree. Leaf

Mutually Recursive Types - Values # let tree = Tree. Node (More (Tree. Leaf 5, (More (Tree. Node (More (Tree. Leaf 3, Last (Tree. Leaf 2))), Last (Tree. Leaf 7))))); ; 9/17/2020 59

Mutually Recursive Types - Values Tree. Node More Last Tree. Leaf Tree. Node Tree.

Mutually Recursive Types - Values Tree. Node More Last Tree. Leaf Tree. Node Tree. Leaf 5 More Last 7 Tree. Leaf 3 2 9/17/2020 60

Mutually Recursive Types - Values A more conventional picture 5 7 3 2 9/17/2020

Mutually Recursive Types - Values A more conventional picture 5 7 3 2 9/17/2020 61

Mutually Recursive Functions # let rec fringe tree = match tree with (Tree. Leaf

Mutually Recursive Functions # let rec fringe tree = match tree with (Tree. Leaf x) -> [x] | (Tree. Node list) -> list_fringe list and list_fringe tree_list = match tree_list with (Last tree) -> fringe tree | (More (tree, list)) -> (fringe tree) @ (list_fringe list); ; val fringe : 'a tree -> 'a list = <fun> val list_fringe : 'a tree. List -> 'a list = <fun> 9/17/2020 62

Mutually Recursive Functions # fringe tree; ; - : int list = [5; 3;

Mutually Recursive Functions # fringe tree; ; - : int list = [5; 3; 2; 7] 9/17/2020 63

Problem # type 'a tree = Tree. Leaf of ’a | Tree. Node of

Problem # type 'a tree = Tree. Leaf of ’a | Tree. Node of 'a tree. List and 'a tree. List = Last of 'a tree | More of ('a tree * 'a tree. List); ; Define tree_size 9/17/2020 64

Problem # type 'a tree = Tree. Leaf of ’a | Tree. Node of

Problem # type 'a tree = Tree. Leaf of ’a | Tree. Node of 'a tree. List and 'a tree. List = Last of 'a tree | More of ('a tree * 'a tree. List); ; Define tree_size let rec tree_size t = match t with Tree. Leaf _ -> | Tree. Node ts -> 9/17/2020 65

Problem # type 'a tree = Tree. Leaf of ’a | Tree. Node of

Problem # type 'a tree = Tree. Leaf of ’a | Tree. Node of 'a tree. List and 'a tree. List = Last of 'a tree | More of ('a tree * 'a tree. List); ; Define tree_size let rec tree_size t = match t with Tree. Leaf _ -> 1 | Tree. Node ts -> tree. List_size ts 9/17/2020 66

Problem # type 'a tree = Tree. Leaf of ’a | Tree. Node of

Problem # type 'a tree = Tree. Leaf of ’a | Tree. Node of 'a tree. List and 'a tree. List = Last of 'a tree | More of ('a tree * 'a tree. List); ; Define tree_size and tree. List_size let rec tree_size t = match t with Tree. Leaf _ -> 1 | Tree. Node ts -> tree. List_size ts and tree. List_size ts = 9/17/2020 67

Problem # type 'a tree = Tree. Leaf of ’a | Tree. Node of

Problem # type 'a tree = Tree. Leaf of ’a | Tree. Node of 'a tree. List and 'a tree. List = Last of 'a tree | More of ('a tree * 'a tree. List); ; Define tree_size and tree. List_size let rec tree_size t = match t with Tree. Leaf _ -> 1 | Tree. Node ts -> tree. List_size ts and tree. List_size ts = match ts with Last t -> | More t ts’ -> 9/17/2020 68

Problem # type 'a tree = Tree. Leaf of ’a | Tree. Node of

Problem # type 'a tree = Tree. Leaf of ’a | Tree. Node of 'a tree. List and 'a tree. List = Last of 'a tree | More of ('a tree * 'a tree. List); ; Define tree_size and tree. List_size let rec tree_size t = match t with Tree. Leaf _ -> 1 | Tree. Node ts -> tree. List_size ts and tree. List_size ts = match ts with Last t -> tree_size t | More t ts’ -> tree_size t + tree. List_size ts’ 9/17/2020 69

Problem # type 'a tree = Tree. Leaf of ’a | Tree. Node of

Problem # type 'a tree = Tree. Leaf of ’a | Tree. Node of 'a tree. List and 'a tree. List = Last of 'a tree | More of ('a tree * 'a tree. List); ; Define tree_size and tree. List_size let rec tree_size t = match t with Tree. Leaf _ -> 1 | Tree. Node ts -> tree. List_size ts and tree. List_size ts = match ts with Last t -> tree_size t | More t ts’ -> tree_size t + tree. List_size ts’ 9/17/2020 70

Nested Recursive Types # type 'a labeled_tree = Tree. Node of ('a * 'a

Nested Recursive Types # type 'a labeled_tree = Tree. Node of ('a * 'a labeled_tree list); ; type 'a labeled_tree = Tree. Node of ('a * 'a labeled_tree list) Mindblowing! What does this mean? What’s the base case? ! 9/17/2020 71

Nested Recursive Type Values # let ltree = Tree. Node(5, [Tree. Node (3, []);

Nested Recursive Type Values # let ltree = Tree. Node(5, [Tree. Node (3, []); Tree. Node (2, [Tree. Node (1, []); Tree. Node (7, [])]); Tree. Node (5, [])]); ; 9/17/2020 72

Nested Recursive Type Values val ltree : int labeled_tree = Tree. Node (5, [Tree.

Nested Recursive Type Values val ltree : int labeled_tree = Tree. Node (5, [Tree. Node (3, []); Tree. Node (2, [Tree. Node (1, []); Tree. Node (7, [])]); Tree. Node (5, [])]) 9/17/2020 73

Nested Recursive Type Values Ltree = Tree. Node(5) : : [ ] Tree. Node(3)

Nested Recursive Type Values Ltree = Tree. Node(5) : : [ ] Tree. Node(3) Tree. Node(2) Tree. Node(5) [ ] : : [ ] Tree. Node(1) Tree. Node(7) [ ] 9/17/2020 74

Nested Recursive Type Values 5 3 2 5 1 7 9/17/2020 75

Nested Recursive Type Values 5 3 2 5 1 7 9/17/2020 75

Mutually Recursive Functions # let rec flatten_tree labtree = match labtree with Tree. Node

Mutually Recursive Functions # let rec flatten_tree labtree = match labtree with Tree. Node (x, treelist) -> x: : flatten_tree_list treelist and flatten_tree_list treelist = match treelist with [] -> [] | labtree: : labtrees -> flatten_tree labtree @ flatten_tree_list labtrees; ; 9/17/2020 76

Mutually Recursive Functions val flatten_tree : 'a labeled_tree -> 'a list = <fun> val

Mutually Recursive Functions val flatten_tree : 'a labeled_tree -> 'a list = <fun> val flatten_tree_list : 'a labeled_tree list -> 'a list = <fun> # flatten_tree ltree; ; - : int list = [5; 3; 2; 1; 7; 5] Nested recursive types lead to mutually recursive functions 9/17/2020 77

Infinite Recursive Values # let rec ones = 1: : ones; ; val ones

Infinite Recursive Values # let rec ones = 1: : ones; ; val ones : int list = [1; 1; . . . ] # match ones with x: : _ -> x; ; Characters 0 -25: Warning: this pattern-matching is not exhaustive. Here is an example of a value that is not matched: [] match ones with x: : _ -> x; ; ^^^^^^^^^^^^^ - : int = 1 9/17/2020 78

Infinite Recursive Values # let rec lab_tree = Tree. Node(2, tree_list) and tree_list =

Infinite Recursive Values # let rec lab_tree = Tree. Node(2, tree_list) and tree_list = [lab_tree; lab_tree]; ; val lab_tree : int labeled_tree = Tree. Node (2, [Tree. Node(. . . ); Tree. Node(. . . )]) val tree_list : int labeled_tree list = [Tree. Node (2, [Tree. Node(. . . ); Tree. Node(. . . )]); Tree. Node (2, [Tree. Node(. . . ); Tree. Node(. . . )])] 9/17/2020 79

Infinite Recursive Values # match lab_tree with Tree. Node (x, _) -> x; ;

Infinite Recursive Values # match lab_tree with Tree. Node (x, _) -> x; ; - : int = 2 9/17/2020 80

Records n n n Records serve the same programming purpose as tuples Provide better

Records n n n Records serve the same programming purpose as tuples Provide better documentation, more readable code Allow components to be accessed by label instead of position n n Labels (aka field names must be unique) Fields accessed by suffix dot notation 9/17/2020 81

Record Types Record types must be declared before they can be used in OCaml

Record Types Record types must be declared before they can be used in OCaml # type person = {name : string; ss : (int * int); age : int}; ; type person = { name : string; ss : int * int; age : int; } n person is the type being introduced n name, ss and age are the labels, or fields n 9/17/2020 82

Record Values Records built with labels; order does not matter # let teacher =

Record Values Records built with labels; order does not matter # let teacher = {name = "Elsa L. Gunter"; age = 102; ss = (119, 73, 6244)}; ; val teacher : person = {name = "Elsa L. Gunter"; ss = (119, 73, 6244); age = 102} n 9/17/2020 83

Record Pattern Matching # let {name = elsa; age = age; ss = (_,

Record Pattern Matching # let {name = elsa; age = age; ss = (_, _, s 3)} = teacher; ; val elsa : string = "Elsa L. Gunter" val age : int = 102 val s 3 : int = 6244 9/17/2020 84

Record Field Access # let soc_sec = teacher. ss; ; val soc_sec : int

Record Field Access # let soc_sec = teacher. ss; ; val soc_sec : int * int = (119, 73, 6244) 9/17/2020 85

Record Values # let student = {ss=(325, 40, 1276); name="Joseph Martins"; age=22}; ; val

Record Values # let student = {ss=(325, 40, 1276); name="Joseph Martins"; age=22}; ; val student : person = {name = "Joseph Martins"; ss = (325, 40, 1276); age = 22} # student = teacher; ; - : bool = false 9/17/2020 86

New Records from Old # let birthday person = {person with age = person.

New Records from Old # let birthday person = {person with age = person. age + 1}; ; val birthday : person -> person = <fun> # birthday teacher; ; - : person = {name = "Elsa L. Gunter"; ss = (119, 73, 6244); age = 103} 9/17/2020 87

New Records from Old # let new_id name soc_sec person = {person with name

New Records from Old # let new_id name soc_sec person = {person with name = name; ss = soc_sec}; ; val new_id : string -> int * int -> person = <fun> # new_id "Guieseppe Martin" (523, 04, 6712) student; ; - : person = {name = "Guieseppe Martin"; ss = (523, 4, 6712); age = 22} 9/17/2020 88