Title: CSE-321 Programming Languages Introduction to Functional Programming (Part II)
1CSE-321 Programming LanguagesIntroduction to
Functional Programming(Part II)
???
2Outline
- Expressions and values V
- Variables V
- Functions V
- Types
- Polymorphism
- Recursion
- Datatypes
- Pattern matching
- Higher-order functions
- Exceptions
- Modules
3What is the Type of ?
All we know about f is that it takes booleans
as arguments.
4f bool -gt ?
fn f gt (f true, f false) (bool -gt ?) -gt ? ?
5f bool -gt 'a
fn f gt (f true, f false) (bool -gt 'a) -gt 'a
'a
- 'a
- type variable
- usually read as alpha
- means 'for any type alpha'
6Polymorphic Types
- Types involving type variables 'a, 'b, 'c, ...
- E.g.
- fn x gt x
- 'a -gt 'a
- fn x gt fn y gt (x, y)
- 'a -gt 'b -gt ('a 'b)
- fn (x 'a) gt fn (y 'a) gt x y
- 'a -gt 'a -gt bool
- ( actually does not typecheck! )
7Equality 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) gt fn (y ''a) gt x y
- ''a -gt ''a -gt bool
8Outline
- Expressions and values V
- Variables V
- Functions V
- Types V
- Recursion
- Datatypes
- Pattern matching
- Higher-order functions
- Exceptions
- Modules
9Recursion 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 lt n
- i)sum n
- Recursion is not an awkward tool if you are used
to functional programming. - Recursion seems elegant but inefficient!
10Recursion in Action
- fun sum n if n 0 then 0else sum (n - 1) n
call stack
0
further computation
...
...
f 10
evaluation
11Funny Recursion
- fun zero n if n 0 then 0else zero (n - 1)
call stack
no further computation
evaluation
12Funny Recursion Optimized
- fun zero n if n 0 then 0else zero (n - 1)
call stack
0
0
...
...
f 10
evaluation
13Funny Recursion Further Optimized
- fun zero n if n 0 then 0else zero (n - 1)
call stack
f 10
...
0
evaluation
14Tail 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!
15Example
- Tail recursive sum
- fun sum' accum k if k 0 then accumelse
- sum' (accum k) (k - 1)
- fun sum n sum' 0 n
- Non-tail recursive sum
- fun sum n if n 0 then 0else sum (n - 1) n
- Think about the invariant of sum
- given
- sum' accum k
- invariant
- accum (k 1) ... n
16Mathematics vs. Computer Science
Math
17Factorial Function
- fac 1 1
- fac n n fac (n - 1)
- Makes sense in
- Math
- CS
- fac 1 1
- fac n fac (n 1) / n
- Makes sense in math.
- But not in CS
- it always diverges.
- "Then what kind of recursive functions are
computationally meaningful?" - ) domain theory in computer science
- Other examples
- real numbers vs. computable real numbers
- logic in math vs. logic in computer science
18Outline
- Expressions and values V
- Variables V
- Functions V
- Types V
- Recursion V
- Datatypes
- Pattern matching
- Higher-order functions
- Exceptions
- Modules
19Enumeration 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?
20Datatypes in SML
- datatype shape Circle Rectangle Triangle
- No flexibility
- e.g.
- Circle 1 (x)
- Triangle - 1 (x)
- Circle Triangle (x)
- But high safety.
21Primitive Set
- datatype set
- Empty
- Singleton
- Pair
- Many
- - Empty
- val it Empty set
- - Many
- val it Many set
22Primitive Set with Arguments
- datatype set
- Empty
- Singleton
- Pair
- Many of int
- - Many 5
- val it Many 5 set
23Primitive Set with Type Parameters
- datatype 'a set
- Empty
- Singleton of 'a
- Pair of 'a 'a
- Many of int
- - Singleton 0
- val it Singleton 0 int set
- - Pair (0, 1)
- val it Pair (0, 1) int set
24Primitive Set with Type Parameters
- datatype 'a set
- Empty
- Singleton of 'a
- Pair of 'a 'a
- Many of int
- - Pair (Singleton 0, Pair (0, 1))
- val it Pair (Singleton 0, Pair (0, 1))
int set set
25Primitive Set with Type Parameters
- datatype 'a set
- Empty
- Singleton of 'a
- Pair of 'a 'a
- Many of int
- - Empty
- val it Empty 'a set
- - Many 5
- val it Many 5 'a set
26Primitive Set with Type Parameters
- datatype 'a set
- Empty
- Singleton of 'a
- Pair of 'a 'a
- Many of int
- - Pair (0, true)
- stdIn27.1-27.15 Error operator and operand
don't agree literal - operator domain int int
- operand int bool
- in expression
- Pair (0,true)
27Recursive Set with Type Parameters
- datatype 'a set
- Empty
- NonEmpty of 'a 'a set
- This is essentially the definition of datatype
list.
28Datatype 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
29Datatype list
- datatype '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)
30Using 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?
31Outline
- Expressions and values V
- Variables V
- Functions V
- Types V
- Recursion V
- Datatypes V
- Pattern matching
- Higher-order functions
- Exceptions
- Modules
32Simple Pattern
- datatype shape Circle Rectangle Triangle
- ( convertToEnum shape -gt int )
- fun convertToEnum (x shape) int
- case x of
- Circle gt 0
- Rectangle gt 1
- Triangle gt 2
33Pattern with Arguments
- datatype 'a set
- Empty
- Singleton of 'a
- Pair of 'a 'a
- Many of int
- fun size (x 'a set) int
- case x of
- Empty gt 0
- Singleton e gt 1
- Pair (e1, e2) gt 2
- Many n gt n
34Wildcard Pattern _ "don't care"
- datatype 'a set
- Empty
- Singleton of 'a
- Pair of 'a 'a
- Many of int
- fun isEmpty (x 'a set) bool
- case x of
- Empty gt true
- _ gt false
35Pattern with Type Annotation
- datatype 'a list
- nil
- of 'a 'a list
- fun length (x 'a list) int
- case x of
- (nil 'a list) gt 0
- (_ 'a) (tail 'a list) gt
- 1 length tail
36Outline
- Expressions and values V
- Variables V
- Functions V
- Types V
- Recursion V
- Datatypes V
- Pattern matching V
- Higher-order functions
- Exceptions
- Modules
37Higher-order Functions
- Take functions as arguments.
- Return functions as the result.
38Why "Higher-order"?
- T0 int bool real unit ...
- T1 T0 -gt T0 T0 ( 1st order )
- T2 T1 -gt T1 T1 ( 2nd order )
- T3 T2 -gt T2 T 2 ( higher order )
- ...
39Higher-order Functions in List
- val exists ('a -gt bool) -gt 'a list -gt bool
- val all ('a -gt bool) -gt 'a list -gt bool
- val map ('a -gt 'b) -gt 'a list -gt 'b list
- val filter ('a -gt bool) -gt 'a list -gt 'a list
- val app ('a -gt unit) -gt 'a list -gt unit
- ( printInt int -gt unit )
- fun printInt i
- TextIO.print ((Int.toString i) "\n" )
- List.app printInt 1, 2, 3
40List Fold Function
- foldl ('a 'b -gt 'b) -gt 'b -gt 'a list -gt 'b
- foldr ('a 'b -gt 'b) -gt 'b -gt 'a list -gt 'b
- foldl f b0 a0, a1, a2, ..., an-1
a2
a0
a1
an-1
an-2
...
b0
bn-2
...
41Examples
- List.exists f l
- List.foldl (fn (a, b) gt b orelse f a) false l
- List.all f l
- List.foldl (fn (a, b) gt b andalso f a) true l
- List.app f l
- List.foldl (fn (a, _) gt f a) () l
- List.map f l
- List.foldr (fn (a, b) gt f a b) nil l
- List.filter f l
- List.foldr (fn (a, b) gt if f a then a b
- else b) nil l
42More Examples
- fun sum (l int list)
- List.foldl (fn (a, accum) gt a accum) 0 l
- fun reverse (l 'a list)
- List.foldl (fn (a, rev) gt a rev) nil l
- Whenever you need iterations over
lists, first consider foldl and foldr.
43Outline
- 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
44Outline
- Expressions and values V
- Variables V
- Functions V
- Types V
- Recursion V
- Datatypes V
- Pattern matching V
- Higher-order functions V
- Exceptions V
- Modules
45Structures and Signatures
- Structure
- collection of type declarations, exceptions,
values, and so on. - structure Set
- struct
- type 'a set 'a list
- val emptySet nil
- fun singleton x x
- fun union s1 s2 s1 _at_ s2
- end
- Signature
- conceptually type of structures.
- signature SET
- sig
- type 'a set
- val emptySet 'a set
- val singleton 'a -gt 'a set
- val union
- 'a set -gt 'a set -gt 'a set
- end
46Structures Signatures
- Transparent constraint
- Type definition is exported to the outside.
- structure Set SET
- struct
- type 'a set 'a list
- val emptySet nil
- fun singleton x x
- fun union s1 s2 s1 _at_ s2
- end
- - Set.singleton 1 1
- val it true bool
- Opaque constraint
- No type definition is exported.
- structure Set gt SET
- struct
- type 'a set 'a list
- val emptySet nil
- fun singleton x x
- fun union s1 s2 s1 _at_ s2
- end
- - Set.singleton 1 1
- ( Error! )
47I need to test your 57 structures!
- structure BetOne gt HW_ONE ...
- structure Bigh2000One gt HW_ONE ...
- structure BoongOne gt HW_ONE
- structure BrandonOne gt HW_ONE ...
- ...
- structure ZiedrichOne gt HW_ONE ...
- How can I test 57 structures?
- They all conform to the same signature.
48Simple (but Ugly) Solution
- fun sumTest f f nil 0 andalso f 1, 2, 3 6
- fun facTest f f 1 1 andalso f 3 6 andalso f
7 5040 - ...
- fun allTest (sum, fac, ...)
- let
- val sumScore if sumTest sum then 10 else 0
- val facScore if facTest fac then 4 else 0
- ...
- in
- sumScore facScore ...
- end
- allTest (BetOne.sum, BetOne.fac, ...)
- allTest (Bigh2000One.sum, Bigh2000One.fac, ...)
- allTest (BoongOne.sum, BoongOne.fac, ...)
- allTest (BrandonOne.sum, BrandonOne.fac, ...)
- ...
- allTest (ZiedrichOne.sum, ZiedrichOne.fac, ...)
49Functors
- Functions on structures
- takes a structure as an argument
- returns a structure as the result
structure
structure
50HW1 Test Functor
- signature HW_TEST
- sig
- val score int
- end
- functor Hw1TestFn (P HW_ONE) HW_TEST
- struct
- structure S Hw1Solution
- val sumScore
- if P.sum nil S.sum nil andalso
- P.sum 1, 2, 3 S.sum 1, 2, 3
- then 10 else 0
- val facScore
- if P.fac 1 S.fac 1 andalso
- P.fac 3 S.fac 3 andalso
- P.fac 7 S.fac 7
- then 4 else 0
- ...
- val score sumScore facScore ...
51HW1 Test Functor in Action
- structure BetOneTest Hw1TestFn (BetOne)
- structure Bigh2000OneTest Hw1TestFn
(Bigh2000One) - structure BoongOneTest Hw1TestFn (BoongOne)
- structure BrandonOneTest Hw1TestFn (BrandonOne)
- ...
- structure ZiedrichOneTest Hw1TestFn
(ZiedrichOne) - BetOneTest.score
- Bigh2000OneTest.score
- BoongOneTest.score
- BrandonOneTest.score
- ...
- ZiedrichOneTest.score
52- So it is YOU who will grade your homework!