CSE321 Programming Languages Introduction to Functional Programming Part
- Slides: 50
CSE-321 Programming Languages Introduction to Functional Programming (Part II) 박성우 POSTECH March 12, 2007
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 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 ? 4
f : bool -> ? fn f => (f true, f false) : (bool -> ? ) -> ? * ? 5
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, . . . • 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. – 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 Recursion Datatypes Pattern matching Higher-order functions Exceptions Modules 9
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 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 (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 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 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 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 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 Recursion V Datatypes Pattern matching Higher-order functions Exceptions Modules 17
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 – e. g. Circle + 1 Triangle - 1 Circle + Triangle (x) (x) • But high safety. 19
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; val it = Many 5 : set 21
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 | 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 | 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 'a * 'a set • This is essentially the definition of datatype list. 25
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 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 – 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 Recursion V Datatypes V Pattern matching Higher-order functions Exceptions Modules 29
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 : set) : int = case x of Empty => 0 | Many n => n 31
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 * '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 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
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 -> 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 -> '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 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) => 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 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 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 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 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. • 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 : > 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 a structure as the result structure 47
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. 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 score! 50
- Cse321
- Introduction to programming languages
- Real-time systems and programming languages
- Cs 421 uiuc
- Thread dalam java
- Programming languages levels
- Plc
- Joey paquet
- Comparative programming languages
- Alternative programming languages
- Types of programming languages
- Transmission programming languages
- Adam doupe cse 340
- Integral data type example
- Xenia programming languages
- Advantages of high level language
- Mainstream programming languages
- Vineeth kashyap
- Programming languages
- Programming languages
- Programming languages
- Programming languages
- Tiny programming language
- Brief history of programming languages
- Lisp_q
- Real-time systems and programming languages
- Xkcd coding
- If programming languages were cars
- Reasons for studying concepts of programming languages
- Cornell programming languages
- Low level linux programming
- Middle level programming languages
- Programming languages flowchart
- Cs 421 uiuc
- Multimedia programming languages
- Storage management in programming languages
- Space maintainer classification
- Non functional plasma enzymes
- Plasma enzyme
- Functional and non functional
- Introduction to scripting languages
- Gtg stands for in automata
- Procedural vs functional
- Fundamentals of functional programming
- Functional programming scheme
- Elm programming language
- Functional programming roadmap
- Lisp functional programming
- Typed functional programming
- Fundamentals of functional programming language
- Cosc 4p41