Thinking Induc,vely. COS 326 David Walker Princeton University

Similar documents
Thinking Induc,vely. COS 326 David Walker Princeton University

A Func'onal Introduc'on. COS 326 David Walker Princeton University

A Second Look At ML. Chapter Seven Modern Programming Languages, 2nd ed. 1

Tuples. CMSC 330: Organization of Programming Languages. Examples With Tuples. Another Example

CMSC 330: Organization of Programming Languages. Functional Programming with Lists

OCaml. ML Flow. Complex types: Lists. Complex types: Lists. The PL for the discerning hacker. All elements must have same type.

Overview. A mathema5cal proof technique Proves statements about natural numbers 0,1,2,... (or more generally, induc+vely defined objects) Merge Sort

Background. CMSC 330: Organization of Programming Languages. Useful Information on OCaml language. Dialects of ML. ML (Meta Language) Standard ML

Dialects of ML. CMSC 330: Organization of Programming Languages. Dialects of ML (cont.) Features of ML. Functional Languages. Features of ML (cont.

CMSC 330: Organization of Programming Languages. Functional Programming with Lists

A Func'onal Space Model

COSE212: Programming Languages. Lecture 4 Recursive and Higher-Order Programming

Programming Languages

Lab 10: OCaml sequences, comparators, stable sorting 12:00 PM, Nov 12, 2017

News. Programming Languages. Complex types: Lists. Recap: ML s Holy Trinity. CSE 130: Spring 2012

Week 5 Tutorial Structural Induction

Programming Languages 3. Definition and Proof by Induction

CSc 372 Comparative Programming Languages

Programming Languages

CSc 372. Comparative Programming Languages. 8 : Haskell Function Examples. Department of Computer Science University of Arizona

Programming Languages

Recap from last time. Programming Languages. CSE 130 : Fall Lecture 3: Data Types. Put it together: a filter function

OCaml Datatypes. COS 326 David Walker* Princeton University

Array Basics: Outline

List Functions, and Higher-Order Functions

PROGRAMMING IN HASKELL. CS Chapter 6 - Recursive Functions

Local defini1ons. Func1on mul1ples- of

OCaml Data CMSC 330: Organization of Programming Languages. User Defined Types. Variation: Shapes in Java

# true;; - : bool = true. # false;; - : bool = false 9/10/ // = {s (5, "hi", 3.2), c 4, a 1, b 5} 9/10/2017 4

Recap. Recap. If-then-else expressions. If-then-else expressions. If-then-else expressions. If-then-else expressions

Booleans (aka Truth Values) Programming Languages and Compilers (CS 421) Booleans and Short-Circuit Evaluation. Tuples as Values.

Implemen'ng OCaml in OCaml

Programming Languages

Recap: ML s Holy Trinity. Story So Far... CSE 130 Programming Languages. Datatypes. A function is a value! Next: functions, but remember.

Programming Languages and Techniques (CIS120)

PROGRAMMING IN HASKELL. Chapter 2 - First Steps

CSE 130 Programming Languages. Datatypes. Ranjit Jhala UC San Diego

Array Basics: Outline

Chapter 3 Linear Structures: Lists

Lecture 6: Sequential Sorting

CSE 130 Programming Languages. Lecture 3: Datatypes. Ranjit Jhala UC San Diego

Haske k ll An introduction to Functional functional programming using Haskell Purely Lazy Example: QuickSort in Java Example: QuickSort in Haskell

OCaml. History, Variants. ML s holy trinity. Interacting with ML. Base type: Integers. Base type: Strings. *Notes from Sorin Lerner at UCSD*

CS Lecture 5: Pattern Matching. Prof. Clarkson Fall Today s music: Puff, the Magic Dragon by Peter, Paul & Mary

CMSC 330: Organization of Programming Languages. OCaml Imperative Programming

Mini-ML. CS 502 Lecture 2 8/28/08

An introduction introduction to functional functional programming programming using usin Haskell

Lecture 19: Functions, Types and Data Structures in Haskell

Begin at the beginning

Func%onal Decomposi%on

Plan (next 4 weeks) 1. Fast forward. 2. Rewind. 3. Slow motion. Rapid introduction to what s in OCaml. Go over the pieces individually

COSE212: Programming Languages. Lecture 3 Functional Programming in OCaml

Recap: ML s Holy Trinity

Which of the following expressions has the type int list?

CS 321 Programming Languages

The Haskell HOP: Higher-order Programming

Case by Case. Chapter 3

OCaml Datatypes. COS 326 David Walker Princeton University

Shell CSCE 314 TAMU. Functions continued

02157 Functional Programming Tagged values and Higher-order list functions

Tail Calls. CMSC 330: Organization of Programming Languages. Tail Recursion. Tail Recursion (cont d) Names and Binding. Tail Recursion (cont d)

Chapter 3 Linear Structures: Lists

Lists. Adrian Groza. Department of Computer Science Technical University of Cluj-Napoca

A Functional Space Model. COS 326 David Walker Princeton University

Side note: Tail Recursion. Begin at the beginning. Side note: Tail Recursion. Base Types. Base Type: int. Base Type: int

Tail Recursion: Factorial. Begin at the beginning. How does it execute? Tail recursion. Tail recursive factorial. Tail recursive factorial

Programming Languages

Poly-HO! COS 326 David Walker Princeton University. polymorphic, higher-order programming

Array Basics: Outline

A First Look at ML. Chapter Five Modern Programming Languages, 2nd ed. 1

Redefinition of an identifier is OK, but this is redefinition not assignment; Thus

CSCE 314 TAMU Fall CSCE 314: Programming Languages Dr. Flemming Andersen. Haskell Functions

CSC324- TUTORIAL 5. Shems Saleh* *Some slides inspired by/based on Afsaneh Fazly s slides

Programming Languages

CS 320: Concepts of Programming Languages

02157 Functional Programming. Michael R. Ha. Tagged values and Higher-order list functions. Michael R. Hansen

CS 457/557: Functional Languages

02157 Functional Programming. Michael R. Ha. Disjoint Unions and Higher-order list functions. Michael R. Hansen

CSCE 314 Programming Languages

The List Datatype. CSc 372. Comparative Programming Languages. 6 : Haskell Lists. Department of Computer Science University of Arizona

Programming Languages

Software Properties as Axioms and Theorems

COP4020 Programming Languages. Functional Programming Prof. Robert van Engelen

Shell CSCE 314 TAMU. Higher Order Functions

CMSC 330: Organization of Programming Languages. Formal Semantics of a Prog. Lang. Specifying Syntax, Semantics

Programming Languages

So what does studying PL buy me?

Theorem Proving Principles, Techniques, Applications Recursion

News. Programming Languages. Recap. Recap: Environments. Functions. of functions: Closures. CSE 130 : Fall Lecture 5: Functions and Datatypes

CS101: Fundamentals of Computer Programming. Dr. Tejada www-bcf.usc.edu/~stejada Week 1 Basic Elements of C++

CSCI-GA Scripting Languages

CSE341: Programming Languages Lecture 2 Functions, Pairs, Lists. Zach Tatlock Winter 2018

Testing. Wouter Swierstra and Alejandro Serrano. Advanced functional programming - Lecture 2. [Faculty of Science Information and Computing Sciences]

CS Lectures 2-3. Introduction to OCaml. Polyvios Pratikakis

This assignment has four parts. You should write your solution to each part in a separate file:

Function definitions. CSE341: Programming Languages Lecture 2 Functions, Pairs, Lists. Example, extended. Some gotchas. Zach Tatlock Winter 2018

CSE341: Programming Languages Lecture 4 Records, Datatypes, Case Expressions. Dan Grossman Spring 2013

Modules and Representa/on Invariants

Processadors de Llenguatge II. Functional Paradigm. Pratt A.7 Robert Harper s SML tutorial (Sec II)

List Processing in Ocaml

Transcription:

Thinking Induc,vely COS 326 David Walker Princeton University slides copyright 2017 David Walker permission granted to reuse these slides for non-commercial educa,onal purposes

Administra,on 2 Assignment 1 due at 11:59 tonight! Program style guide: hlp://www.cs.princeton.edu/~cos326/style.php Read notes: func,onal basics, type-checking, typed programming thinking induc,vely (today) Real World OCaml Chapter 2, 3

Op,ons 3 A value v has type t op,on if it is either: the value None, or a value Some v', and v' has type t Op,ons can signal there is no useful result to the computa,on Example: we look up a value in a hash table using a key. If the key is present, return Some v where v is the associated value If the key is not present, we return None

Slope between two points (x1, y1) c a b 4 type point = float * float (x2, y2) let slope (p1:point) (p2:point) : float =

Slope between two points (x1, y1) c a b 5 type point = float * float (x2, y2) let slope (p1:point) (p2:point) : float = let (x1,y1) = p1 in let (x2,y2) = p2 in deconstruct tuple

Slope between two points (x1, y1) c a b 6 type point = float * float (x2, y2) let slope (p1:point) (p2:point) : float = let (x1,y1) = p1 in let (x2,y2) = p2 in let xd = x2 -. x1 in if xd!= 0.0 then (y2 -. y1) /. xd else avoid divide by zero??? what can we return?

Slope between two points (x1, y1) c a b 7 type point = float * float (x2, y2) let slope (p1:point) (p2:point) : float option = let (x1,y1) = p1 in let (x2,y2) = p2 in let xd = x2 -. x1 in if xd!= 0.0 then??? else??? we need an op,on type as the result type

Slope between two points (x1, y1) c a b 8 type point = float * float (x2, y2) let slope (p1:point) (p2:point) : float option = let (x1,y1) = p1 in let (x2,y2) = p2 in let xd = x2 -. x1 in if xd!= 0.0 then Some ((y2 -. y1) /. xd) else None

Slope between two points (x1, y1) c a b 9 type point = float * float (x2, y2) let slope (p1:point) (p2:point) : float option = let (x1,y1) = p1 in let (x2,y2) = p2 in let xd = x2 -. x1 in if xd!= 0.0 then (y2 -. y1) /. xd else None Has type float Can have type float op,on

Slope between two points (x1, y1) c a b 10 type point = float * float (x2, y2) let slope (p1:point) (p2:point) : float option = let (x1,y1) = p1 in let (x2,y2) = p2 in let xd = x2 -. x1 in if xd!= 0.0 then (y2 -. y1) /. xd else None Has type float Can have type float op,on WRONG: Type mismatch

Slope between two points (x1, y1) c a b 11 type point = float * float (x2, y2) let slope (p1:point) (p2:point) : float option = let (x1,y1) = p1 in let (x2,y2) = p2 in let xd = x2 -. x1 in if xd!= 0.0 then (y2 -. y1) /. xd else None Has type float doubly WRONG: result does not match declared result

Remember the typing rule for if 12 if e1 : bool and e2 : t and e3 : t (for some type t) then if e1 then e2 else e3 : t Returning an op,onal value from an if statement: if then None : t op,on else Some ( ) : t op,on

How do we use an op,on? 13 slope : point -> point -> float option returns a float op,on

How do we use an op,on? 14 slope : point -> point -> float option let print_slope (p1:point) (p2:point) : unit =

How do we use an op,on? 15 slope : point -> point -> float option let print_slope (p1:point) (p2:point) : unit = slope p1 p2 returns a float op,on; to print we must discover if it is None or Some

How do we use an op,on? 16 slope : point -> point -> float option let print_slope (p1:point) (p2:point) : unit = match slope p1 p2 with

How do we use an op,on? 17 slope : point -> point -> float option let print_slope (p1:point) (p2:point) : unit = match slope p1 p2 with Some s -> None -> There are two possibili,es Ver,cal bar separates possibili,es

How do we use an op,on? 18 slope : point -> point -> float option let print_slope (p1:point) (p2:point) : unit = match slope p1 p2 with Some s -> None -> The "Some s" palern includes the variable s The object between and -> is called a palern

How do we use an op,on? 19 slope : point -> point -> float option let print_slope (p1:point) (p2:point) : unit = match slope p1 p2 with Some s -> print_string ("Slope: " ^ string_of_float s) None -> print_string "Vertical line.\n"

Wri,ng Func,ons Over Typed Data 20 Steps to wri,ng func,ons over typed data: 1. Write down the func,on and argument names 2. Write down argument and result types 3. Write down some examples (in a comment) 4. Deconstruct input data structures 5. Build new output values 6. Clean up by iden,fying repeated palerns For op,on types: when the input has type t op,on, deconstruct with: when the output has type t op,on, construct with: match with None -> Some s -> Some ( ) None

MORE PATTERN MATCHING 21

Recall the Distance Func,on 22 type point = float * float let distance (p1:point) (p2:point) : float = let square x = x *. x in let (x1,y1) = p1 in let (x2,y2) = p2 in sqrt (square (x2 -. x1) +. square (y2 -. y1))

Recall the Distance Func,on 23 type point = float * float let distance (p1:point) (p2:point) : float = let square x = x *. x in let (x1,y1) = p1 in let (x2,y2) = p2 in sqrt (square (x2 -. x1) +. square (y2 -. y1)) ;; (x2, y2) is an example of a palern a palern for tuples. So let declara,ons can contain palerns just like match statements The difference is that a match allows you to consider mul,ple different data shapes

Recall the Distance Func,on 24 type point = float * float let distance (p1:point) (p2:point) : float = let square x = x *. x in match p1 with (x1,y1) -> let (x2,y2) = p2 in sqrt (square (x2 -. x1) +. square (y2 -. y1)) ;; There is only 1 possibility when matching a pair

Recall the Distance Func,on 25 type point = float * float let distance (p1:point) (p2:point) : float = let square x = x *. x in match p1 with (x1,y1) -> match p2 with (x2,y2) -> sqrt (square (x2 -. x1) +. square (y2 -. y1)) ;; We can nest one match expression inside another. (We can nest any expression inside any other, if the expressions have the right types)

BeLer Style: Complex PaLerns 26 we built a pair of pairs type point = float * float let distance (p1:point) (p2:point) : float = let square x = x *. x in match (p1, p2) with ((x1,y1), (x2, y2)) -> sqrt (square (x2 -. x1) +. square (y2 -. y1)) ;; PaLern for a pair of pairs: ((variable, variable), (variable, variable)) All the variable names in the palern must be different.

BeLer Style: Complex PaLerns 27 we built a pair of pairs type point = float * float let distance (p1:point) (p2:point) : float = let square x = x *. x in match (p1, p2) with (p3, p4) -> let (x1, y1) = p3 in let (x2, y2) = p4 in sqrt (square (x2 -. x1) +. square (y2 -. y1)) ;; A palern must be consistent with the type of the expression in between match with We use (p3, p4) here instead of ((x1, y1), (x2, y2))

PaLern-matching in func,on parameters 28 type point = float * float let distance ((x1,y1):point) ((x2,y2):point) : float = let square x = x *. x in sqrt (square (x2 -. x1) +. square (y2 -. y1)) ;; Func,on parameters are palerns too!

What s the best style? 29 let distance (p1:point) (p2:point) : float = let square x = x *. x in let (x1,y1) = p1 in let (x2,y2) = p2 in sqrt (square (x2 -. x1) +. square (y2 -. y1)) let distance ((x1,y1):point) ((x2,y2):point) : float = let square x = x *. x in sqrt (square (x2 -. x1) +. square (y2 -. y1)) Either of these is reasonably clear and compact. Code with unnecessary nested matches/lets is par,cularly ugly to read. You'll be judged on code style in this class.

What s the best style? 30 let distance (x1,y1) (x2,y2) = let square x = x *. x in sqrt (square (x2 -. x1) +. square (y2 -. y1)) This is how I'd do it... the types for tuples + the tuple palerns are a lille ugly/verbose... but for now in class, use the explicit type annota,ons. We will loosen things up later in the semester.

Combining palerns 31 type point = float * float (* returns a nearby point in the graph if one exists *) nearby : graph -> point -> point option let printer (g:graph) (p:point) : unit = match nearby g p with None -> print_string "could not find one\n" Some (x,y) -> print_float x; print_string ", "; print_float y; print_newline(); ;;

Other PaLerns Constant values can be used as palerns 32 let small_prime (n:int) : bool = match n with 2 -> true 3 -> true 5 -> true _ -> false ;; let iffy (b:bool) : int = match b with true -> 0 false -> 1 ;; the underscore palern matches anything it is the "don't care" palern

INDUCTIVE THINKING 33

Induc,ve Programming and Proving 34 An induc&ve data type T is a data type defined by: a collec,on of base cases that don t refer to T a collec,on of induc,ve cases that build new values of type T from pre-exis,ng data of type T the pre-exis,ng data is guarateed to be smaller than the new values Programming principle: solve programming problem for base cases solve programming problem for induc,ve cases by calling func,on recursively (induc,vely) on smaller data value Proving principle: prove program sa,sfies property P for base cases prove induc,ve cases sa,sfy property P assuming induc,ve calls on smaller data values sa,sfy property P

LISTS: AN INDUCTIVE DATA TYPE 35

Lists are Recursive Data 36 In OCaml, a list value is: [ ] (the empty list) v :: vs (a value v followed by a shorter list of values vs) Induc,ve Case Base Case

Lists are Induc,ve Data 37 In OCaml, a list value is: [ ] (the empty list) v :: vs (a value v followed by a shorter list of values vs) An example: 2 :: 3 :: 5 :: [ ] has type int list is the same as: 2 :: (3 :: (5 :: [ ])) "::" is called "cons" An alterna,ve syntax ( syntac,c sugar for lists): [2; 3; 5] But this is just a shorthand for 2 :: 3 :: 5 :: []. If you ever get confused fall back on the 2 basic constructors: :: and []

Typing rules for lists: Typing Lists 38 (1) [ ] may have any list type t list (2) if e1 : t and e2 : t list then (e1 :: e2) : t list

Typing Lists 39 Typing rules for lists: (1) [ ] may have any list type t list (2) if e1 : t and e2 : t list then (e1 :: e2) : t list More examples: (1 + 2) :: (3 + 4) :: [ ] :?? (2 :: [ ]) :: (5 :: 6 :: [ ]) :: [ ] :?? [ [2]; [5; 6] ] :??

Typing Lists 40 Typing rules for lists: (1) [ ] may have any list type t list (2) if e1 : t and e2 : t list then (e1 :: e2) : t list More examples: (1 + 2) :: (3 + 4) :: [ ] : int list (2 :: [ ]) :: (5 :: 6 :: [ ]) :: [ ] : int list list [ [2]; [5; 6] ] : int list list (Remember that the 3 rd example is an abbrevia,on for the 2 nd )

Another Example 41 What type does this have? [ 2 ] :: [ 3 ]

Another Example 42 What type does this have? [ 2 ] :: [ 3 ] int list int list # [2] :: [3];; Error: This expression has type int but an expression was expected of type int list #

Another Example 43 What type does this have? [ 2 ] :: [ 3 ] int list int list Give me a simple fix that makes the expression type check?

Another Example 44 What type does this have? [ 2 ] :: [ 3 ] int list int list Give me a simple fix that makes the expression type check? Either: 2 :: [ 3 ] : int list Or: [ 2 ] :: [ [ 3 ] ] : int list list

Analyzing Lists Just like op,ons, there are two possibili,es when deconstruc,ng lists. Hence we use a match with two branches 45 (* return Some v, if v is the first list element; return None, if the list is empty *) let head (xs : int list) : int option =

Analyzing Lists Just like op,ons, there are two possibili,es when deconstruc,ng lists. Hence we use a match with two branches 46 (* return Some v, if v is the first list element; return None, if the list is empty *) let head (xs : int list) : int option = match xs with [] -> hd :: _ -> we don't care about the contents of the tail of the list so we use the underscore

Analyzing Lists Just like op,ons, there are two possibili,es when deconstruc,ng lists. Hence we use a match with two branches 47 (* return Some v, if v is the first list element; return None, if the list is empty *) let head (xs : int list) : int option = match xs with [] -> None hd :: _ -> Some hd This func,on isn't recursive -- we only extracted a small, fixed amount of informa,on from the list -- the first element

A more interes,ng example 48 (* Given a list of pairs of integers, produce the list of products of the pairs *) prods [(2,3); (4,7); (5,2)] == [6; 28; 10]

A more interes,ng example 49 (* Given a list of pairs of integers, produce the list of products of the pairs *) prods [(2,3); (4,7); (5,2)] == [6; 28; 10] let rec prods (xs : (int * int) list) : int list =

A more interes,ng example 50 (* Given a list of pairs of integers, produce the list of products of the pairs *) prods [(2,3); (4,7); (5,2)] == [6; 28; 10] let rec prods (xs : (int * int) list) : int list = match xs with [] -> (x,y) :: tl ->

A more interes,ng example 51 (* Given a list of pairs of integers, produce the list of products of the pairs *) prods [(2,3); (4,7); (5,2)] == [6; 28; 10] let rec prods (xs : (int * int) list) : int list = match xs with [] -> [] (x,y) :: tl ->

A more interes,ng example 52 (* Given a list of pairs of integers, produce the list of products of the pairs *) prods [(2,3); (4,7); (5,2)] == [6; 28; 10] let rec prods (xs : (int * int) list) : int list = match xs with [] -> [] (x,y) :: tl ->?? ::?? the result type is int list, so we can speculate that we should create a list

A more interes,ng example 53 (* Given a list of pairs of integers, produce the list of products of the pairs *) prods [(2,3); (4,7); (5,2)] == [6; 28; 10] let rec prods (xs : (int * int) list) : int list = match xs with [] -> [] (x,y) :: tl -> (x * y) ::?? the first element is the product

A more interes,ng example 54 (* Given a list of pairs of integers, produce the list of products of the pairs *) prods [(2,3); (4,7); (5,2)] == [6; 28; 10] let rec prods (xs : (int * int) list) : int list = match xs with [] -> [] (x,y) :: tl -> (x * y) ::?? to complete the job, we must compute the products for the rest of the list

A more interes,ng example 55 (* Given a list of pairs of integers, produce the list of products of the pairs *) prods [(2,3); (4,7); (5,2)] == [6; 28; 10] let rec prods (xs : (int * int) list) : int list = match xs with [] -> [] (x,y) :: tl -> (x * y) :: prods tl

Three Parts to Construc,ng a Func,on 56 (1) Think about how to break down the input in to cases: let rec prods (xs : (int*int) This assump&on list) is called : int the list = match xs with Induc&on Hypothesis. You ll use it to prove your program [] ->... correct. (x,y) :: tl ->... (2) Assume the recursive call on smaller data is correct. (3) Use the result of the recursive call to build correct answer. let rec prods (xs : (int*int) list) : int list =... (x,y) :: tl ->... prods tl...

Another example: zip 57 (* Given two lists of integers, return None if the lists are different lengths otherwise stitch the lists together to create Some of a list of pairs *) zip [2; 3] [4; 5] == Some [(2,4); (3,5)] zip [5; 3] [4] == None zip [4; 5; 6] [8; 9; 10; 11; 12] == None (Give it a try.)

Another example: zip 58 let rec zip (xs : int list) (ys : int list) : (int * int) list option =

Another example: zip 59 let rec zip (xs : int list) (ys : int list) : (int * int) list option = match (xs, ys) with

Another example: zip 60 let rec zip (xs : int list) (ys : int list) : (int * int) list option = match (xs, ys) with ([], []) -> ([], y::ys') -> (x::xs', []) -> (x::xs', y::ys') ->

Another example: zip 61 let rec zip (xs : int list) (ys : int list) : (int * int) list option = match (xs, ys) with ([], []) -> Some [] ([], y::ys') -> (x::xs', []) -> (x::xs', y::ys') ->

Another example: zip 62 let rec zip (xs : int list) (ys : int list) : (int * int) list option = match (xs, ys) with ([], []) -> Some [] ([], y::ys') -> None (x::xs', []) -> None (x::xs', y::ys') ->

Another example: zip 63 let rec zip (xs : int list) (ys : int list) : (int * int) list option = match (xs, ys) with ([], []) -> Some [] ([], y::ys') -> None (x::xs', []) -> None (x::xs', y::ys') -> (x, y) :: zip xs' ys' is this ok?

Another example: zip 64 let rec zip (xs : int list) (ys : int list) : (int * int) list option = match (xs, ys) with ([], []) -> Some [] ([], y::ys') -> None (x::xs', []) -> None (x::xs', y::ys') -> (x, y) :: zip xs' ys' No! zip returns a list op,on, not a list! We need to match it and decide if it is Some or None.

Another example: zip 65 let rec zip (xs : int list) (ys : int list) : (int * int) list option = match (xs, ys) with ([], []) -> Some [] ([], y::ys') -> None (x::xs', []) -> None (x::xs', y::ys') -> (match zip xs' ys' with None -> None Some zs -> (x,y) :: zs) Is this ok?

Another example: zip 66 let rec zip (xs : int list) (ys : int list) : (int * int) list option = match (xs, ys) with ([], []) -> Some [] ([], y::ys') -> None (x::xs', []) -> None (x::xs', y::ys') -> (match zip xs' ys' with None -> None Some zs -> Some ((x,y) :: zs))

Another example: zip 67 let rec zip (xs : int list) (ys : int list) : (int * int) list option = match (xs, ys) with ([], []) -> Some [] (x::xs', y::ys') -> (match zip xs' ys' with None -> None Some zs -> Some ((x,y) :: zs)) (_, _) -> None Clean up. Reorganize the cases. PaLern matching proceeds in order.

A bad list example 68 let rec sum (xs : int list) : int = match xs with hd::tl -> hd + sum tl

A bad list example 69 let rec sum (xs : int list) : int = match xs with hd::tl -> hd + sum tl # Characters 39-78:..match xs with hd :: tl -> hd + sum tl.. Warning 8: this pattern-matching is not exhaustive. Here is an example of a value that is not matched: [] val sum : int list -> int = <fun>

INSERTION SORT 70

Recall Inser,on Sort 71 At any point during the inser,on sort: some ini,al segment of the array will be sorted the rest of the array will be in the same (unsorted) order as it was originally -5-2 3-4 10 6 7 sorted unsorted

Recall Inser,on Sort 72 At any point during the inser,on sort: some ini,al segment of the array will be sorted the rest of the array will be in the same (unsorted) order as it was originally -5-2 3-4 10 6 7 sorted unsorted At each step, take the next item in the array and insert it in order into the sorted por,on of the list -5-4 -2 3 10 6 7 sorted unsorted

Inser,on Sort With Lists 73 The algorithm is similar, except instead of one array, we will maintain two lists, a sorted list and an unsorted list list 1: list 2: -5-2 3-4 10 6 7 sorted unsorted We'll factor the algorithm: a func,on to insert into a sorted list a sor,ng func,on that repeatedly inserts

Insert 74 (* insert x in to sorted list xs *) let rec insert (x : int) (xs : int list) : int list =

Insert 75 (* insert x in to sorted list xs *) let rec insert (x : int) (xs : int list) : int list = match xs with [] -> hd :: tl -> a familiar palern: analyze the list by cases

Insert 76 (* insert x in to sorted list xs *) let rec insert (x : int) (xs : int list) : int list = match xs with [] -> [x] hd :: tl -> insert x into the empty list

Insert 77 (* insert x in to sorted list xs *) let rec insert (x : int) (xs : int list) : int list = match xs with [] -> [x] hd :: tl -> if hd < x then hd :: insert x tl build a new list with: hd at the beginning the result of inser,ng x in to the tail of the list awerwards

Insert 78 (* insert x in to sorted list xs *) let rec insert (x : int) (xs : int list) : int list = match xs with [] -> [x] hd :: tl -> if hd < x then hd :: insert x tl else x :: xs put x on the front of the list, the rest of the list follows

Inser,on Sort 79 type il = int list insert : int -> il -> il (* insertion sort *) let rec insert_sort(xs : il) : il =

Inser,on Sort 80 type il = int list insert : int -> il -> il (* insertion sort *) let rec insert_sort(xs : il) : il = let rec aux (sorted : il) (unsorted : il) : il = in

Inser,on Sort 81 type il = int list insert : int -> il -> il (* insertion sort *) let rec insert_sort(xs : il) : il = let rec aux (sorted : il) (unsorted : il) : il = in aux [] xs

Inser,on Sort 82 type il = int list insert : int -> il -> il (* insertion sort *) let rec insert_sort(xs : il) : il = let rec aux (sorted : il) (unsorted : il) : il = match unsorted with [] -> hd :: tl -> in aux [] xs

Inser,on Sort 83 type il = int list insert : int -> il -> il (* insertion sort *) let rec insert_sort(xs : il) : il = let rec aux (sorted : il) (unsorted : il) : il = match unsorted with [] -> sorted hd :: tl -> aux (insert hd sorted) tl in aux [] xs

A SHORT JAVA RANT 84

Defini,on and Use of Java Pairs 85 public class Pair { public class User { } public int x; public int y; public Pair (int a, int b) { x = a; y = b; } } public Pair swap (Pair p1) { Pair p2 = new Pair(p1.y, p1.x); } return p2; What could go wrong?

A Paucity of Types 86 public class Pair { public class User { } public int x; public int y; public Pair (int a, int b) { x = a; y = b; } } public Pair swap (Pair p1) { Pair p2 = new Pair(p1.y, p1.x); } return p2; The input p1 to swap may be null and we forgot to check. Java has no way to define a pair data structure that is just a pair. How many students in the class have seen an accidental null pointer excep&on thrown in their Java code?

From Java Pairs to OCaml Pairs 87 In OCaml, if a pair may be null it is a pair op,on: type java_pair = (int * int) option

From Java Pairs to OCaml Pairs 88 In OCaml, if a pair may be null it is a pair op,on: type java_pair = (int * int) option And if you write code like this: let swap_java_pair (p:java_pair) : java_pair = let (x,y) = p in (y,x)

From Java Pairs to OCaml Pairs 89 In OCaml, if a pair may be null it is a pair op,on: type java_pair = (int * int) option And if you write code like this: let swap_java_pair (p:java_pair) : java_pair = let (x,y) = p in (y,x) You get a helpful error message like this: # Characters 91-92: let (x,y) = p in (y,x);; ^ Error: This expression has type java_pair = (int * int) option but an expression was expected of type 'a * 'b

From Java Pairs to OCaml Pairs 90 type java_pair = (int * int) option And what if you were up at 3am trying to finish your COS 326 assignment and you accidentally wrote the following sleep-deprived, brain-dead statement? let swap_java_pair (p:java_pair) : java_pair = match p with Some (x,y) -> Some (y,x)

From Java Pairs to OCaml Pairs 91 type java_pair = (int * int) option And what if you were up at 3am trying to finish your COS 326 assignment and you accidentally wrote the following sleep-deprived, brain-dead statement? let swap_java_pair (p:java_pair) : java_pair = match p with Some (x,y) -> Some (y,x) OCaml to the rescue!..match p with Some (x,y) -> Some (y,x) Warning 8: this pattern-matching is not exhaustive. Here is an example of a value that is not matched: None

From Java Pairs to OCaml Pairs 92 type java_pair = (int * int) option And what if you were up at 3am trying to finish your COS 326 assignment and you accidentally wrote the following sleep-deprived, brain-dead statement? let swap_java_pair (p:java_pair) : java_pair = match p with Some (x,y) -> Some (y,x) An easy fix! let swap_java_pair (p:java_pair) : java_pair = match p with None -> None Some (x,y) -> Some (y,x)

From Java Pairs to OCaml Pairs 93 Moreover, your pairs are probably almost never null! Defensive programming & always checking for null is

From Java Pairs to OCaml Pairs 94 There just isn't always some "good thing" for a func,on to do when it receives a bad input, like a null pointer In OCaml, all these issues disappear when you use the proper type for a pair and that type contains no "extra junk type pair = int * int Once you know OCaml, it is hard to write swap incorrectly Your bullet-proof code is much simpler than in Java. let swap (p:pair) : pair = let (x,y) = p in (y,x)

Summary of Java Pair Rant 95 Java has a paucity of types There is no type to describe just the pairs There is no type to describe just the triples There is no type to describe the pairs of pairs There is no type OCaml has many more types use op,on when things may be null do not use op,on when things are not null OCaml types describe data structures more precisely programmers have fewer cases to worry about en,re classes of errors just go away type checking and palern analysis help prevent programmers from ever forgeyng about a case

Summary of Java Pair Rant 96 Java has a paucity of types There is no type to describe just the pairs There is no type to describe just the triples There is no type to describe the pairs of pairs There is no type OCaml has many more types SCORE: OCAML 1, JAVA 0 use op,on when things may be null do not use op,on when things are not null ocaml types describe data structures more precisely programmers have fewer cases to worry about en,re classes of errors just go away type checking and palern analysis help prevent programmers from ever forgeyng about a case

Example problems to prac,ce 97 Write a func,on to sum the elements of a list sum [1; 2; 3] ==> 6 Write a func,on to append two lists append [1;2;3] [4;5;6] ==> [1;2;3;4;5;6] Write a func,on to reverse a list rev [1;2;3] ==> [3;2;1] Write a func,on to turn a list of pairs into a pair of lists split [(1,2); (3,4); (5,6)] ==> ([1;3;5], [2;4;6]) Write a func,on that returns all prefixes of a list prefixes [1;2;3] ==> [[]; [1]; [1;2]; [1;2;3]] suffixes