CSE-321 Programming Languages Introduction to Functional Programming (Part II) POSTECH March 12, 2007 박박박
Mar 18, 2016
CSE-321 Programming Languages
Introduction to Functional Programming(Part II)
POSTECHMarch 12, 2007
박성우
2
Outline• Expressions and values V• Variables V• Functions V• Types
– Polymorphism• Recursion• Datatypes• Pattern matching• Higher-order functions• Exceptions• Modules
3
What is the Type of ?
true,
false)
(
fn f => (f true, f false)
f
f
f
All we know about f is that it takes booleans as arguments.
4
f
All we know about f is that it takes booleans as arguments.
bool
?
5
f : bool -> ?
fn f => (f true, f false) : (bool -> ?) -> ? * ?
6
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'
7
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 -> 'a -> bool(* actually does not typecheck! *)
8
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 -> ''a -> bool
9
Outline• Expressions and values V• Variables V• Functions V• Types V• Recursion• Datatypes• Pattern matching• Higher-order functions• Exceptions• Modules
10
Recursion vs. Iteration• Recursion in SML
fun sum n =if n = 0 then 0else 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 toolif you are used to functional programming.
• Recursion seems elegant but inefficient!
11
Recursion in Actionfun sum n =
if n = 0 then 0else sum (n - 1) + n
call stack
evaluationf 10
f 8f 9
...
f 1f 0
55
36 + 945 + 10
...0 + 1
1 + 2
0further computation
12
Funny Recursionfun zero n =
if n = 0 then 0else zero (n - 1)
call stack
evaluationf 10
f 9f 8
...
f 1f 0
00
0
00
...0
no further computation
13
Funny Recursion Optimizedfun zero n =
if n = 0 then 0else zero (n - 1)
call stack
evaluationf 10
f 9f 8
...
f 1f 0
000
00
...
0
14
Funny Recursion Further Optimizedfun zero n =
if n = 0 then 0else zero (n - 1)
call stack
evaluationf 10 f 9 f 8 .
.
.
f 1 f 0 0
15
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!
16
Example• Tail recursive sumfun sum' accum k =
if k = 0 then accumelse sum' (accum + k) (k - 1)
fun sum n = sum' 0 n
• Non-tail recursive sumfun sum n =
if n = 0 then 0else sum (n - 1) + n
• Think about the invariant of sum:– given:
sum' accum k– invariant:
accum = n + (n - 1) + ... (k + 1)
17
Outline• Expressions and values V• Variables V• Functions V• Types V• Recursion V• Datatypes• Pattern matching• Higher-order functions• Exceptions• Modules
18
Enumeration Types in Cenum shape { Circle, Rectangle, Triangle};
• Great flexibility– e.g.
Circle + 1 == RectangleTriangle - 1 == Rectangle(Circle + Triangle) / 2 == Rectangle
• But is this good or bad?
19
Datatypes in SMLdatatype shape = Circle | Rectangle | Triangle
• No flexibility– e.g.
Circle + 1 (x)Triangle - 1 (x)Circle + Triangle (x)
• But high safety.
20
Setdatatype set =
Empty | Many
- Empty;val it = Empty : set- Many;val it = Many : set
21
Set with Argumentsdatatype set =
Empty | Many of int
- Many 5;val it = Many 5 : set
22
Set with Type Parametersdatatype '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
23
Set with Type Parametersdatatype '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 set
24
Set with Type Parametersdatatype 'a set =
Empty | Singleton of 'a | Pair of 'a * 'a
- Pair (0, true);stdIn:27.1-27.15 Error: operator and operand
don't agree [literal] operator domain: int * int operand: int * bool in expression: Pair (0,true)
25
Recursive Set with Type Parametersdatatype 'a set =
Empty | NonEmpty of 'a * 'a set
• This is essentially the definition of datatype list.
26
Datatype listdatatype 'a list =
nil | :: of 'a * 'a list
- nil;val it = [] : 'a list- 2 :: nil; (* :: infix *)val it = [2] : int list- 1 :: (2 :: nil);val it = [1,2] : int list- 1 :: 2 :: nil; (* :: right associative *)val it = [1,2] : int list
27
Datatype listdatatype 'a list =
nil | :: of 'a * 'a list
- 1 :: [2] :: nil;- [1] :: 2 :: nil;- [1] :: [2] :: nil;val it = [[1],[2]] : int list list- [1] :: [[2]];val it = [[1],[2]] : int list list
(X)(X)
28
Using Datatypes• We know how to create values of various datatypes:
– shape– set– int set– int list– ...
• But how do we use them in programming?• What is the point of creating datatype values that
are never used?
29
Outline• Expressions and values V• Variables V• Functions V• Types V• Recursion V• Datatypes V• Pattern matching• Higher-order functions• Exceptions• Modules
30
Simple Patterndatatype shape = Circle | Rectangle |
Triangle
(* convertToEnum : shape -> int *)fun convertToEnum (x : shape) : int =
case x ofCircle => 0
| Rectangle => 1| Triangle => 2
31
Pattern with Argumentsdatatype set =
Empty | Many of int
fun size (x : set) : int =case x ofEmpty => 0
| Many n => n
32
Wildcard Pattern _ : "don't care"datatype 'a set =
Empty | Singleton of 'a | Pair of 'a * 'a
fun isEmpty (x : 'a set) : bool =case x ofEmpty => true
| _ => false
33
Pattern with Type Annotationdatatype '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
34
Outline• Expressions and values V• Variables V• Functions V• Types V• Recursion V• Datatypes V• Pattern matching V• Higher-order functions• Exceptions• Modules
35
Higher-order Functions• Take functions as arguments.• Return functions as the result.
36
Why "Higher-order"?• T0 ::= int | bool | real | unit | ...• T1 ::= T0 -> T0 | T0 (* 1st order *)• T2 ::= T1 -> T1 | T1 (* 2nd order *)• T3 ::= T2 -> T2 | T2 (* higher
order *)• ...
37
Higher-order Functions in List• val exists : ('a -> bool) -> 'a list -> bool• val all : ('a -> bool) -> 'a list -> bool• val map : ('a -> 'b) -> 'a list -> 'b list• val filter : ('a -> bool) -> 'a list -> 'a list• val app : ('a -> unit) -> 'a list -> unit
(* printInt : int -> unit *)fun printInt i = TextIO.print ((Int.toString i) ^ "\n" );List.app printInt [1, 2, 3];
38
List Fold Function• foldl : ('a * 'b -> 'b) -> 'b -> 'a list -> 'b
foldr : ('a * 'b -> 'b) -> 'b -> 'a list -> 'b
• foldl f b0 [a0, a1, a2, ..., an-1]
b0
a0
f b1
a1
f b2
an-1
f bn
a2
f b3 bn-2
an-2
f bn-1...
...
39
Summationfun sum (l : int list) =
List.foldl (fn (a, accum) => a + accum) 0 l
• foldl op+ 0 [a0, a1, a2, ..., an-1]
0
a0
+ ¢
a1
+ ¢
an-1
+
a2
+ ¢ ¢
an-2
+ ¢ ...
...
op+
40
List Reversalfun 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.
41
More ExamplesList.exists f l =
List.foldl (fn (a, b) => b orelse f a) false lList.all f l =
List.foldl (fn (a, b) => b andalso f a) true lList.app f l =
List.foldl (fn (a, _) => f a) () l List.map f l =
List.foldr (fn (a, b) => f a :: b) nil lList.filter f l =
List.foldr (fn (a, b) => if f a then a :: b else b) nil l
42
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
43
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
44
Structures and Signatures• Structure
– collection of type declarations, exceptions, values, and so on.
structure Set =struct
type 'a set = 'a listval emptySet = nilfun singleton x = [x]fun union s1 s2 = s1 @ s2
end
• Signature– conceptually type of
structures.
signature SET =sig
type 'a setval emptySet : 'a setval singleton : 'a -> 'a setval union : 'a set -> 'a set -> 'a set
end
45
Structures + Signatures• Transparent constraint
– Type definition is exported to the outside.
structure Set : SET =struct
type 'a set = 'a listval emptySet = nilfun singleton x = [x]fun union s1 s2 = s1 @ s2
end
- Set.singleton 1 = [1];val it = true : bool
• Opaque constraint– No type definition is
exported.structure Set :> SET =struct
type 'a set = 'a listval emptySet = nilfun singleton x = [x]fun union s1 s2 = s1 @ s2
end
- Set.singleton 1 = [1];(* Error! *)
46
We need to test your 46 structures!structure ahwbestOne :> HW_ONE = ...structure bopyOne :> HW_ONE = ...structure diozzOne :> HW_ONE = structure freeOne :> HW_ONE = ......structure zistinOne :> HW_ONE = ...
• How can we test 46 structures? ) They all conform to the same signature. ) We use a functor!
47
Functors• Functions on structures
– takes a structure as an argument– returns a structure as the result
structure
structure
48
HW1 Test Functorsignature HW_TEST =sig
val score : intend
structure S = HwSolOne
functor Hw1TestFn (P : HW_ONE val name : string) : HW_TEST =
structopen P...val sumScore = test "sum" 5 sum S.sum [1, 5, 10]
val facScore = test "fac" 5 fac S.fac [1, 5, 10 ] val gcdScore = test "gcd" 4 gcd S.gcd [(15,20), (24,12), (10000,0)]
... val cartprodScore = test "cartprod" 8 (cartprod [1,2,3]) (S.cartprod [1,2,3]) [["a","b","c","d"]]
val score = sumScore + facScore + ... + cardprodScoreval _ = print ("\n " ^ name ^ ", score : " ^ (Int.toString score) ^ "\n" )...
end
49
HW1 Test Functor in Actionstructure ahwbestOneTest =
Hw1TestFn (structure P = ahwbestOne val name = "ahwbest")
structure bopyOneTest = Hw1TestFn (structure P = bopyOne
val name = "bopy")structure diozzOneTest =
Hw1TestFn (structure P = diozzOneval name = "diozz")
structure freeOneTest = Hw1TestFn (structure P = freeOne
val name = "free")...structure zistinOneTest =
Hw1TestFn (structure P = zistinOneval name = "zistin")
50
So it is YOU who will grade your homework!
Learn functors to find your score!