CSE321 Programming Languages Introduction to Functional Programming Part

  • Slides: 50
Download presentation
CSE-321 Programming Languages Introduction to Functional Programming (Part II) 박성우 POSTECH March 12, 2007

CSE-321 Programming Languages Introduction to Functional Programming (Part II) 박성우 POSTECH March 12, 2007

Outline • • • Expressions and values V Variables V Functions V Types –

Outline • • • Expressions and values V Variables V Functions V Types – Polymorphism Recursion Datatypes Pattern matching Higher-order functions Exceptions Modules 2

What is the Type of f ? All we know about f is that

What is the Type of f ? All we know about f is that it takes booleans as arguments. fn f => (f true, f false) ( f true, f false) 3

All we know about f is that it takes booleans as arguments. bool f

All we know about f is that it takes booleans as arguments. bool f ? 4

f : bool -> ? fn f => (f true, f false) : (bool

f : bool -> ? fn f => (f true, f false) : (bool -> ? ) -> ? * ? 5

f : bool -> 'a fn f => (f true, f false) : (bool

f : bool -> 'a fn f => (f true, f false) : (bool -> 'a) -> 'a * 'a • 'a – type variable – usually read as alpha – means 'for any type alpha' 6

Polymorphic Types • Types involving type variables 'a, 'b, 'c, . . . •

Polymorphic Types • Types involving type variables 'a, 'b, 'c, . . . • E. g. – fn x => x : 'a -> 'a – fn x => fn y => (x, y) : 'a -> 'b -> ('a * 'b) – fn (x : 'a) => fn (y : 'a) => x = y : 'a -> bool (* actually does not typecheck! *) 7

Equality Types • Motivation – Equality (=) is not defined on every type. –

Equality Types • Motivation – Equality (=) is not defined on every type. – E. g. • comparing two functions for equality? • Type variables with equality – ''a, ''b, ''c, . . . – ''a means 'for any type alpha for which equality is defined' – fn (x : ''a) => fn (y : ''a) => x = y : ''a -> bool 8

Outline • • • Expressions and values V Variables V Functions V Types V

Outline • • • Expressions and values V Variables V Functions V Types V Recursion Datatypes Pattern matching Higher-order functions Exceptions Modules 9

Recursion vs. Iteration • Recursion in SML fun sum n = if n =

Recursion vs. Iteration • Recursion in SML fun sum n = if n = 0 then 0 else sum (n - 1) + n • Iteration in C int i, sum; for (i = 0, sum = 0; i <= n; i++) sum += n; • Recursion is not an awkward tool if you are used to functional programming. • Recursion seems elegant but inefficient! 10

Recursion in Action fun sum n = if n = 0 then 0 else

Recursion in Action fun sum n = if n = 0 then 0 else sum (n - 1) + n call stack 0 f 1 f 9 f 10 further computation 1 + 2. . . f 8 0 + 1 36 + 9 45 + 10 55 evaluation 11

Funny Recursion fun zero n = if n = 0 then 0 else zero

Funny Recursion fun zero n = if n = 0 then 0 else zero (n - 1) call stack 0 f 1 f 9 f 10 no further computation 0. . . f 8 0 0 evaluation 12

Funny Recursion Optimized fun zero n = if n = 0 then 0 else

Funny Recursion Optimized fun zero n = if n = 0 then 0 else zero (n - 1) call stack 0 f 1 f 9 f 10 0. . . f 8 0 0 evaluation 13

Funny Recursion Further Optimized fun zero n = if n = 0 then 0

Funny Recursion Further Optimized fun zero n = if n = 0 then 0 else zero (n - 1) call stack f 10 f 9 f 8 . . . f 1 f 0 0 evaluation 14

Tail Recursive Function • A tail recursive function f: – A recursive call to

Tail Recursive Function • A tail recursive function f: – A recursive call to f is the last step in evaluating the function body. – That is, no more computation remains after calling f itself. • A tail recursive call needs no stack! • A tail recursive call is as efficient as iteration! 15

Example • Non-tail recursive sum fun sum n = if n = 0 then

Example • Non-tail recursive sum fun sum n = if n = 0 then 0 else sum (n - 1) + n • Tail recursive sum fun sum' accum k = if k = 0 then accum else sum' (accum + k) (k - 1) fun sum n = sum' 0 n • Think about the invariant of sum: – given: sum' accum k – invariant: accum = n + (n - 1) +. . . (k + 1) 16

Outline • • • Expressions and values V Variables V Functions V Types V

Outline • • • Expressions and values V Variables V Functions V Types V Recursion V Datatypes Pattern matching Higher-order functions Exceptions Modules 17

Enumeration Types in C enum shape { Circle, Rectangle, Triangle}; • Great flexibility –

Enumeration Types in C enum shape { Circle, Rectangle, Triangle}; • Great flexibility – e. g. Circle + 1 == Rectangle Triangle - 1 == Rectangle (Circle + Triangle) / 2 == Rectangle • But is this good or bad? 18

Datatypes in SML datatype shape = Circle | Rectangle | Triangle • No flexibility

Datatypes in SML datatype shape = Circle | Rectangle | Triangle • No flexibility – e. g. Circle + 1 Triangle - 1 Circle + Triangle (x) (x) • But high safety. 19

Set datatype set = Empty | Many - Empty; val it = Empty :

Set datatype set = Empty | Many - Empty; val it = Empty : set - Many; val it = Many : set 20

Set with Arguments datatype set = Empty | Many of int - Many 5;

Set with Arguments datatype set = Empty | Many of int - Many 5; val it = Many 5 : set 21

Set with Type Parameters datatype 'a set = Empty | Singleton of 'a |

Set with Type Parameters datatype 'a set = Empty | Singleton of 'a | Pair of 'a * 'a - Singleton 0; val it = Singleton 0 : int set - Pair (0, 1); val it = Pair (0, 1) : int set 22

Set with Type Parameters datatype 'a set = Empty | Singleton of 'a |

Set with Type Parameters datatype 'a set = Empty | Singleton of 'a | Pair of 'a * 'a - Pair (Singleton 0, Pair (0, 1)) val it = Pair (Singleton 0, Pair (0, 1)) : int set 23

Set with Type Parameters datatype 'a set = Empty | Singleton of 'a |

Set with Type Parameters datatype 'a set = Empty | Singleton of 'a | Pair of 'a * 'a - Pair (0, true); std. In: 27. 1 -27. 15 Error: operator and operand don't agree [literal] operator domain: int * int operand: int * bool in expression: Pair (0, true) 24

Recursive Set with Type Parameters datatype 'a set = Empty | Non. Empty of

Recursive Set with Type Parameters datatype 'a set = Empty | Non. Empty of 'a * 'a set • This is essentially the definition of datatype list. 25

Datatype list datatype 'a list = nil | : : of 'a * 'a

Datatype list datatype 'a list = nil | : : of 'a * 'a list - nil; val it = [] : 'a list - 2 : : nil; val it = [2] : int list - 1 : : (2 : : nil); val it = [1, 2] : int list - 1 : : 2 : : nil; val it = [1, 2] : int list (* : : infix *) (* : : right associative *) 26

Datatype list datatype 'a list = nil | : : of 'a * 'a

Datatype list datatype 'a list = nil | : : of 'a * 'a list (X) - 1 : : [2] : : nil; (X) - [1] : : 2 : : nil; - [1] : : [2] : : nil; val it = [[1], [2]] : int list - [1] : : [[2]]; val it = [[1], [2]] : int list 27

Using Datatypes • We know how to create values of various datatypes: – shape

Using Datatypes • We know how to create values of various datatypes: – shape – set – int list –. . . • But how do we use them in programming? • What is the point of creating datatype values that are never used? 28

Outline • • • Expressions and values V Variables V Functions V Types V

Outline • • • Expressions and values V Variables V Functions V Types V Recursion V Datatypes V Pattern matching Higher-order functions Exceptions Modules 29

Simple Pattern datatype shape = Circle | Rectangle | Triangle (* convert. To. Enum

Simple Pattern datatype shape = Circle | Rectangle | Triangle (* convert. To. Enum : shape -> int *) fun convert. To. Enum (x : shape) : int = case x of Circle => 0 | Rectangle => 1 | Triangle => 2 30

Pattern with Arguments datatype set = Empty | Many of int fun size (x

Pattern with Arguments datatype set = Empty | Many of int fun size (x : set) : int = case x of Empty => 0 | Many n => n 31

Wildcard Pattern _ : "don't care" datatype 'a set = Empty | Singleton of

Wildcard Pattern _ : "don't care" datatype 'a set = Empty | Singleton of 'a | Pair of 'a * 'a fun is. Empty (x : 'a set) : bool = case x of Empty => true | _ => false 32

Pattern with Type Annotation datatype 'a list = nil | : : of 'a

Pattern with Type Annotation datatype 'a list = nil | : : of 'a * 'a list fun length (x : 'a list) : int = case x of (nil : 'a list) => 0 | (_ : 'a) : : (tail : 'a list) => 1 + length tail 33

Outline • • • Expressions and values V Variables V Functions V Types V

Outline • • • Expressions and values V Variables V Functions V Types V Recursion V Datatypes V Pattern matching V Higher-order functions Exceptions Modules 34

Higher-order Functions • Take functions as arguments. • Return functions as the result. 35

Higher-order Functions • Take functions as arguments. • Return functions as the result. 35

Why "Higher-order"? • • • T 0 T 1 T 2 T 3. .

Why "Higher-order"? • • • T 0 T 1 T 2 T 3. . . : : = int | T 0 -> T 1 -> T 2 -> bool T 0 | T 1 | T 2 | | real T 0 T 1 T 2 | (* (* (* unit |. . . 1 st order *) 2 nd order *) higher order *) 36

Higher-order Functions in List • • • val val val exists : ('a ->

Higher-order Functions in List • • • val val val exists : ('a -> bool) -> 'a list -> bool all : ('a -> bool) -> 'a list -> bool map : ('a -> 'b) -> 'a list -> 'b list filter : ('a -> bool) -> 'a list app : ('a -> unit) -> 'a list -> unit (* print. Int : int -> unit *) fun print. Int i = Text. IO. print ((Int. to. String i) ^ "n" ); List. app print. Int [1, 2, 3]; 37

List Fold Function • foldl : ('a * 'b -> 'b) -> 'b ->

List Fold Function • foldl : ('a * 'b -> 'b) -> 'b -> 'a list -> 'b foldr : ('a * 'b -> 'b) -> 'b -> 'a list -> 'b • foldl f b 0 [a 0, a 1, a 2, . . . , an-1] a 0 a 1 b 0 f b 1 f a 2 . . . an-2 b 2 f b 3. . . bn-2 f an-1 bn-1 f bn 38

Summation fun sum (l : int list) = op+=> a + accum) 0 l

Summation fun sum (l : int list) = op+=> a + accum) 0 l List. foldl (fn (a, accum) • foldl op+ 0 [a 0, a 1, a 2, . . . , an-1] a 0 0 + a 1 ¢ + ¢ a 2 . . . an-2 + ¢. . . ¢ + an-1 ¢ + 39

List Reversal fun reverse (l : 'a list) = List. foldl (fn (a, rev)

List Reversal fun reverse (l : 'a list) = List. foldl (fn (a, rev) => a : : rev) nil l fun reverse (l : 'a list) = List. foldl op: : nil l • Whenever you need iterations over lists, first consider foldl and foldr. 40

More Examples List. exists f l = List. foldl (fn (a, b) => b

More Examples List. exists f l = List. foldl (fn (a, b) => b orelse f a) false l List. all f l = List. foldl (fn (a, b) => b andalso f a) true l List. app f l = List. foldl (fn (a, _) => f a) () l List. map f l = List. foldr (fn (a, b) => f a : : b) nil l List. filter f l = List. foldr (fn (a, b) => if f a then a : : b else b) nil l 41

Outline • • • Expressions and values V Variables V Functions V Types V

Outline • • • Expressions and values V Variables V Functions V Types V Recursion V Datatypes V Pattern matching V Higher-order functions V Exceptions – exception: please see the course notes. • Modules 42

Outline • • • Expressions and values V Variables V Functions V Types V

Outline • • • Expressions and values V Variables V Functions V Types V Recursion V Datatypes V Pattern matching V Higher-order functions V Exceptions V Modules 43

Structures and Signatures • Structure – collection of type declarations, exceptions, values, and so

Structures and Signatures • Structure – collection of type declarations, exceptions, values, and so on. • Signature – conceptually type of structures. structure Set = struct type 'a set = 'a list val empty. Set = nil fun singleton x = [x] fun union s 1 s 2 = s 1 @ s 2 end signature SET = sig type 'a set val empty. Set : 'a set val singleton : 'a -> 'a set val union : 'a set -> 'a set end 44

Structures + Signatures • Transparent constraint – Type definition is exported to the outside.

Structures + Signatures • Transparent constraint – Type definition is exported to the outside. • Opaque constraint – No type definition is exported. structure Set : SET = struct type 'a set = 'a list val empty. Set = nil fun singleton x = [x] fun union s 1 s 2 = s 1 @ s 2 end structure Set : > SET = struct type 'a set = 'a list val empty. Set = nil fun singleton x = [x] fun union s 1 s 2 = s 1 @ s 2 end - Set. singleton 1 = [1]; val it = true : bool - Set. singleton 1 = [1]; (* Error! *) 45

We need to test your 46 structures! structure. . . structure ahwbest. One :

We need to test your 46 structures! structure. . . structure ahwbest. One : > HW_ONE =. . . bopy. One : > HW_ONE =. . . diozz. One : > HW_ONE = free. One : > HW_ONE =. . . zistin. One : > HW_ONE =. . . • How can we test 46 structures? ) They all conform to the same signature. ) We use a functor! 46

Functors • Functions on structures – takes a structure as an argument – returns

Functors • Functions on structures – takes a structure as an argument – returns a structure as the result structure 47

HW 1 Test Functor signature HW_TEST = sig val score : int end structure

HW 1 Test Functor signature HW_TEST = sig val score : int end structure S = Hw. Sol. One functor Hw 1 Test. Fn (P : HW_ONE val name : string) : HW_TEST = struct open P. . . val sum. Score = test "sum" 5 sum S. sum [1, 5, 10] val fac. Score = test "fac" 5 fac S. fac [1, 5, 10 ] val gcd. Score = test "gcd" 4 gcd S. gcd [(15, 20), (24, 12), (10000, 0)]. . . val cartprod. Score = test "cartprod" 8 (cartprod [1, 2, 3]) (S. cartprod [1, 2, 3]) [["a", "b", "c", "d"]] end val score = sum. Score + fac. Score +. . . + cardprod. Score val _ = print ("n " ^ name ^ ", score : " ^ (Int. to. String score) ^ "n" ). . . 48

HW 1 Test Functor in Action structure ahwbest. One. Test = Hw 1 Test.

HW 1 Test Functor in Action structure ahwbest. One. Test = Hw 1 Test. Fn (structure P = ahwbest. One val name = "ahwbest") structure bopy. One. Test = Hw 1 Test. Fn (structure P = bopy. One val name = "bopy") structure diozz. One. Test = Hw 1 Test. Fn (structure P = diozz. One val name = "diozz") structure free. One. Test = Hw 1 Test. Fn (structure P = free. One val name = "free"). . . structure zistin. One. Test = Hw 1 Test. Fn (structure P = zistin. One val name = "zistin") 49

So it is YOU who will grade your homework! Learn functors to find your

So it is YOU who will grade your homework! Learn functors to find your score! 50