+ All Categories
Home > Documents > Lecture 7 Principles of Functional Programming Summer...

Lecture 7 Principles of Functional Programming Summer...

Date post: 26-Jun-2020
Category:
Upload: others
View: 1 times
Download: 0 times
Share this document with a friend
44
Lecture 7 Principles of Functional Programming Summer 2020 Datatypes
Transcript
Page 1: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Lecture 7Principles of Functional Programming

Summer 2020

Datatypes

Page 2: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Section 1

Trees

Jacob Neumann Datatypes 28 May 2020 2 / 44

Page 3: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Binary trees in SML

We define a new type tree with the following syntax (which we’lldiscuss more later):7.0

1 datatype tree =

2 Empty | Node of tree * int * tree

This declares a new type called tree whose constructors areEmpty and Node . Empty is a constant constructor because it’sjust a value of type tree . Node takes in an argument of typetree*int*tree and produces another tree .

All trees are either of the form Empty or Node(L,x,R) for somex : int (referred to as the root of the tree), some L : tree

(referred to as the left subtree), and some R : tree (referred toas the right subtree)

Jacob Neumann Datatypes 28 May 2020 3 / 44

Page 4: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

E

7.2

1 Empty

Jacob Neumann Datatypes 28 May 2020 4 / 44

Page 5: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

1

E E

7.3

1 Node(Empty ,1,Empty)

Jacob Neumann Datatypes 28 May 2020 5 / 44

Page 6: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

1

E 2

E E

7.4

1 Node(Empty ,1,Node(Empty ,2,Empty))

Jacob Neumann Datatypes 28 May 2020 6 / 44

Page 7: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

1

E 2

E 3

E 4

E 5

E E

7.5

1 Node(Empty ,1,Node(Empty ,2,Node(Empty ,3,Node(

Empty ,4,Node(Empty ,5,Empty)))))

Jacob Neumann Datatypes 28 May 2020 7 / 44

Page 8: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

1

2

E E

3

E E

7.6

1 Node(Node(Empty ,2,Empty),1,Node(Empty ,3,Empty)

)

Jacob Neumann Datatypes 28 May 2020 8 / 44

Page 9: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

1

2

E E

3

4

E E

E

7.7

1 Node(Node(Empty ,2,Empty),1,Node(Node(Empty ,4,

Empty) ,3,Empty))

Jacob Neumann Datatypes 28 May 2020 9 / 44

Page 10: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

1

2

E E

4

3

5

E E

E

E

7.8

1 Node(Node(Empty ,2,Empty),1,Node(Node(Node(

Empty ,5,Empty),3,Empty),4,Empty))

Jacob Neumann Datatypes 28 May 2020 10 / 44

Page 11: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

1

E 2

3

E 4

E E

E

7.9

1 Node(Empty ,1,Node(Node(Empty ,3,Node(Empty ,4,

Empty)) ,2,Empty))

Jacob Neumann Datatypes 28 May 2020 11 / 44

Page 12: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

1

2

4

8

E E

9

E E

5

10

E E

11

E E

3

6

E 13

E E

7

14

E E

E

7.10

1 Node(Node(Node(Node(Empty ,8,Empty),4,Node(

Empty ,9,Empty)),2,Node(Node(Empty ,10, Empty)

,5,Node(Empty ,11, Empty))),1,Node(Node(Empty

,6,Node(Empty ,13, Empty)),3,Node(Node(Empty

,14, Empty),7,Empty)))

Jacob Neumann Datatypes 28 May 2020 12 / 44

Page 13: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Traversals

Inorder7.12

1 fun inord (Empty:tree):int list = []

2 | inord (Node(L,x,R)) =

3 (inord L) @ (x::inord R)

Jacob Neumann Datatypes 28 May 2020 13 / 44

Page 14: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Traversals

Preorder7.13

1 fun preord (Empty:tree):int list = []

2 | preord (Node(L,x,R)) =

3 x::(( preord L) @ (preord R))

Jacob Neumann Datatypes 28 May 2020 14 / 44

Page 15: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Minimum

7.14

1 fun min (Empty:tree , default:int) = default

2 | min (Node(L,x,R),default) =

3 let

4 (* Parallel *)

5 val (minL ,minR) =

6 (min(L,default), min(R,default))

7 in

8 (* Constant -time *)

9 Int.min(x,Int.min(minL ,minR))

10 end

Jacob Neumann Datatypes 28 May 2020 15 / 44

Page 16: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Analyzing the work & span of tree functions

To analyze the runtime complexity of functions defined by recursion ontrees, we need a notion of size for trees. It turns out that we have two:

Depth/height: the length (number of nodes) in the longest pathfrom the root to any leaf node7.1

1 fun height (Empty:tree):int = 0

2 | height (Node(L,_,R)) =

3 1 + Int.max(height L,height R)

Size: the number of nodes in the tree7.11

1 fun size (Empty:tree):int = 0

2 | size (Node(L,_,R)) =

3 1 + (size L) + (size R)

We’ll use both.

Jacob Neumann Datatypes 28 May 2020 16 / 44

Page 17: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Balanced Trees

We’ll say a tree is balanced if both its subtrees are balanced and both ofits subtrees have approximately the same height (their heights differ byat most one).

On balanced trees, you can assume a recursive call to the leftsubtree costs approximately the same amount of time as on theright subtree.

If n is the size of a balanced tree, and d is its height, then we canassume

n ≈ 2d

Jacob Neumann Datatypes 28 May 2020 17 / 44

Page 18: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Depth-Analysis of min

0 Notion of size: depth d of the input tree

1 Recurrences:

Wmin(0) = k0

Wmin(d) ≤ k1 + 2Wmin(d− 1)

Smin(0) = k0

Smin(d) ≤ k1 + Smin(d− 1)

2-4 . . .

5 Wmin(d) is O(2d), Smin(d) is O(d)

Remember: if the input tree is balanced, then 2d ≈ n, where n is thesize (number of nodes).

Jacob Neumann Datatypes 28 May 2020 18 / 44

Page 19: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Size-Analysis of preord

0 Notion of size: number of nodes n of the input

1 Recurrences:

Wpreord(0) = k0

Wpreord(n) = 2Wpreord(n/2) + kn

NOTE: This assumes the tree is balanced

Spreord(0) = k0

Spreord(n) ≤ Spreord(n/2) + kn

2-4 . . .

5 Wpreord(n) is O(n log n), Spreord(n) is O(n)

Jacob Neumann Datatypes 28 May 2020 19 / 44

Page 20: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

(pause for questions)

Jacob Neumann Datatypes 28 May 2020 20 / 44

Page 21: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Section 2

Structural Induction

Jacob Neumann Datatypes 28 May 2020 21 / 44

Page 22: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Induction Principle

Recall that for lists, the two constructors were [] and:: of t * t list where t is the type of list we’re dealing with.Subsequently, the induction principle for lists was that if P ([]) and ifP (xs) implies P (x::xs), then P (L) holds for all L.

Principle of Structural Induction on Trees: If P (Empty) holds and,for all values L:tree , R:tree and values x:int, P (L) and P (R)implies P (Node(L,x,R)).

Jacob Neumann Datatypes 28 May 2020 22 / 44

Page 23: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Example: Reversing Trees

7.15

1 fun revTree (Empty:tree):tree = Empty

2 | revTree (Node(L,x,R) =

3 Node(revTree R,x,revTree L)

7.12

1 fun inord (Empty:tree):int list = []

2 | inord (Node(L,x,R)) =

3 (inord L) @ (x::inord R)

Thm. For all values T:tree ,

rev (inord T) ∼= inord(revTree T)

Jacob Neumann Datatypes 28 May 2020 23 / 44

Page 24: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

When life hands you lemmas...

Lemma 1 For all valuable expressions L1:int list ,L2:int list ,

rev (L1@L2) ∼= (rev L2)@(rev L1)

Lemma 2 inord is total

Lemma 3 rev is total

Lemma 4 For all valuable expressions L1:int list ,L2:int list , and all values x:int,

(L1@[x])@L2 ∼= L1@(x::L2)

Lemma 5 revTree is total

Jacob Neumann Datatypes 28 May 2020 24 / 44

Page 25: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Thm. For all values T:tree ,

rev (inord T) ∼= inord(revTree T)

Proof of Thm

BC T=Empty

rev (inord Empty)

∼= rev [] (defn of inord)∼= [] (defn of rev)∼= inord Empty (defn inord)∼= inord (revTree Empty) (defn revTree)

Jacob Neumann Datatypes 28 May 2020 25 / 44

Page 26: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Example: Reversing Trees

IS T=Node(L,x,R) for some values L,R:tree and x:int

IH1 rev(inord L) ∼= inord(revTree L)

IH2 rev(inord R) ∼= inord(revTree R)

rev(inord (Node(L,x,R)))

∼= rev(( inord L)@(x::( inord R))) (defn inord)

∼= (rev (x::inord R)) @ (rev(inord L)) ( Lemma 1,2 )

∼= ((rev (inord R))@[x]) @ (rev(inord L))

( Lemma 2 , defn of rev)

∼= (rev (inord R))@(x::(rev(inord L)))

( Lemma 2,3,4 )

Jacob Neumann Datatypes 28 May 2020 26 / 44

Page 27: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Example: Reversing Trees

∼= (rev (inord R))@(x::(rev(inord L)))

( Lemma 2,3,4 )

∼= inord(revTree R) @ (x::inord(revTree L))

( IH1,2 )

∼= inord(Node(revTree R,x,revTree L))

( Lemma 5 , defn inord)

∼= inord(revTree(Node(L,x,R))) (defn revTree)

Jacob Neumann Datatypes 28 May 2020 27 / 44

Page 28: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

(pause for questions)

Jacob Neumann Datatypes 28 May 2020 28 / 44

Page 29: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Section 3

Datatypes

Jacob Neumann Datatypes 28 May 2020 29 / 44

Page 30: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Notice some similarities. . .

All natural numbers are either 0 or n+1 for some natural numbern. To prove P (n) for all natural numbers n, we prove P (0) andprove that P (n) implies P (n+1).

All values of type t list are either [] or x::xs for some x:t

and some value xs:t list . To prove P (L) for all valuesL:int list , we prove P ([]) and prove that P (xs) impliesP (x::xs) for arbitrary x:t.

All value of type tree are either Empty or Node(L,x,R) forsome x:int and some values L and R of type tree . To proveP (T) for all values T:tree , we prove P (Empty) and prove thatP (L) and P (R) together imply P (Node(L,x,R)) for arbitraryx:int.

What’s the general pattern?

Jacob Neumann Datatypes 28 May 2020 30 / 44

Page 31: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

The datatype keyword

7.16

1 datatype foo = Abcd

2 | Qwerty of int * string

3 | Zyxwv of int * foo

Abcd is a constant constructor, i.e. a constructor value of typefoo

Qwerty is a constructor of the foo type, which takes in anargument of type int*string . Qwerty can also be thought of(and used) as a function value of type int * string -> foo.

Zyxwv is a constructor of the foo type, which takes in anargument of type int * foo. Zyxwv can also be thought of(and used) as a function value of type int * foo -> foo

Jacob Neumann Datatypes 28 May 2020 31 / 44

Page 32: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Recursion on defined datatypes

7.17

1 val f1 : foo = Abcd

2 val f2 : foo = Qwerty (15,"onefifty")

3 val f3 : foo = Zyxwv (150,f2)

7.18

1 fun toInt Abcd = 2

2 | toInt (Qwerty(n,_)) = n

3 | toInt (Zyxwv (k,F)) = k + toInt F

Jacob Neumann Datatypes 28 May 2020 32 / 44

Page 33: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Induction on defined datatypes

Thm. For all values f : foo, P (f).

Proof By induction on f

BC f=Abcd

(proof of P (Abcd))

BC f=Qwerty(n,s) for some values n:int, s:string

(proof of P (Qwerty(n,s)) for arbitrary n,s)

IS f=Zyxwv(n,f’) for some values n:int, f’:foo

IH P (f’)

(proof of P (Zyxwv(n,f)) for arbitrary n, using IH )

Jacob Neumann Datatypes 28 May 2020 33 / 44

Page 34: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Examples

Natural Numbers

datatype nat = Zero

| Succ of nat

fun toInt Zero = 0

| toInt (Succ n) = 1 + toInt n

fun fromInt 0 = Zero

| fromInt n = Succ(fromInt (n-1))

Note: natFact is total, even though fact is not:

fun fact 0 = 1 | fact n = n * fact(n-1)

fun natFact (N : nat):int =

fact(toInt N)

Jacob Neumann Datatypes 28 May 2020 34 / 44

Page 35: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Examples

Trees7.0

1 datatype tree =

2 Empty | Node of tree * int * tree

Lists

datatype ’t list =

[] | :: of ’t * ’t list

infixr ::

(Note: This is not exactly how lists are defined)

Parametrized by a type variable (more about this on Monday):: is also infixed

Jacob Neumann Datatypes 28 May 2020 35 / 44

Page 36: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

New Example: options

The parametrized datatype option is pre-defined in SML:

datatype ’t option = NONE | SOME of ’t

For every type t, there is a type t option

NONE is a value (and a constructor) of type t option .

SOME is a constructor of the t option type: if x:t, thenSOME(x) is a value of type t option . SOME is also a functionvalue of type t -> t option .

We can case on options by pattern-matching the constructors:

case (thing : bool option option) of

(SOME(SOME true)) => ...

| (SOME _ ) => ...

| NONE => ...

Can do structural induction on options

Jacob Neumann Datatypes 28 May 2020 36 / 44

Page 37: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Section 4

Example: Days of the Week

Jacob Neumann Datatypes 28 May 2020 37 / 44

Page 38: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Type Aliases

7.19

1 type giantTuple = int * int * int * int * int

* int * int * int

Jacob Neumann Datatypes 28 May 2020 38 / 44

Page 39: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Days of the Week

7.20

1 datatype day =

2 Sunday | Monday | Tuesday | Wednesday |

Thursday | Friday | Saturday

7.21

1 fun nextDay Saturday = Sunday

2 | nextDay Friday = Saturday

3 | nextDay Thursday = Friday

4 | nextDay Wednesday = Thursday

5 | nextDay Tuesday = Wednesday

6 | nextDay Monday = Tuesday

7 | nextDay Sunday = Monday

Jacob Neumann Datatypes 28 May 2020 39 / 44

Page 40: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Day of the Week

7.22

1 datatype month = Jan | Feb | Mar | Apr

2 | May | Jun | Jul | Aug

3 | Sep | Oct | Nov | Dec

4 type date = int

dayOfWeek : month * date -> day

REQUIRES: DD ≥ 0ENSURES: dayOfWeek(MM,DD) evaluates to what day of theweek it was on the DDth day of the month of MM, 2020. Eachmonth is counted as if it went on forever, sodayOfWeek(Apr ,197000) should return what day of the weekit is, 196970 days after April 2020 concludes.

Jacob Neumann Datatypes 28 May 2020 40 / 44

Page 41: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Hard-code New Year’s Day

7.23

1 fun dayOfWeek (Jan:month ,01: date):day =

Wednesday

Jacob Neumann Datatypes 28 May 2020 41 / 44

Page 42: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Carry over months

7.24

1 | dayOfWeek (Feb ,01) =

2 nextDay(dayOfWeek (Jan ,31))

3 | dayOfWeek (Mar ,01) =

4 nextDay(dayOfWeek (Feb ,29))

5 | dayOfWeek (Apr ,01) =

6 nextDay(dayOfWeek (Mar ,31))

7 | dayOfWeek (May ,01) =

8 nextDay(dayOfWeek (Apr ,30))

9 | dayOfWeek (Jun ,01) =

10 nextDay(dayOfWeek (May ,31))

11 | dayOfWeek (Jul ,01) =

12 nextDay(dayOfWeek (Jun ,30))

13 | dayOfWeek (Aug ,01) =

14 nextDay(dayOfWeek (Jul ,31))

15 | dayOfWeek (Sep ,01) =

16 nextDay(dayOfWeek (Aug ,31))

17 | dayOfWeek (Oct ,01) =

18 nextDay(dayOfWeek (Sep ,30))

19 | dayOfWeek (Nov ,01) =

20 nextDay(dayOfWeek (Oct ,31))

21 | dayOfWeek (Dec ,01) =

22 nextDay(dayOfWeek (Nov ,30))

Jacob Neumann Datatypes 28 May 2020 42 / 44

Page 43: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Then recur

7.25

1 | dayOfWeek (MM ,DD) = nextDay(dayOfWeek (MM,

DD -1))

Jacob Neumann Datatypes 28 May 2020 43 / 44

Page 44: Lecture 7 Principles of Functional Programming Summer 202015150/resources/lectures/7/lecture7.pdf · 2 Empty | Nodeoftree *int* tree This declares a new type called tree whose constructors

Thank you!

Jacob Neumann Datatypes 28 May 2020 44 / 44


Recommended