Download PPT

Document related concepts
no text concepts found
Transcript
CSE-321 Programming Languages
Introduction to Functional Programming
박성우
POSTECH
Programming Paradigms
• Structured programming
– C, Pascal, …
• Object-oriented programming
– C++, Java, …
• Logic programming
– Prolog, …
• Functional programming
– SML, Haskell, Objective Caml, Lisp, Scheme, F#,
…
2
Outline
•
•
•
•
•
•
•
•
•
•
Expressions and values
Variables
Functions
Types
Recursion
Datatypes
Pattern matching
Higher-order functions
Exceptions
Modules
3
Imperative Language C
• A program consists of commands.
– command = “do something”
• Nothing wrong:
if (x == 1) then
x = x + 1;
else
x = x - 1;
• Nothing wrong either:
if (x == 1) then
x = x + 1;
4
Functional Language OCaml
• A program consists of expressions.
– expression = “obtain a value”
• Nothing wrong:
if (x = 1) then
x + 1
else
x - 1
• But this does not make sense:
if (x = 1) then
x + 1
– what is the value if x <> 1?
5
Evaluation
Expression
Value
• An expression “evaluates” to a value.
• We “evaluate” an expression to obtain a value.
6
Integer Evaluation
1 + 1
2
1 - 1
0
1 * 1
1
…
7
Boolean Evaluation
1 = 1
true
1 <> 1
false
1 <> 0
true
…
8
An Integer Expression
if 1 = -1 then 10
else -10
if false then 10
else -10
-10
9
Values as Expressions
1
???
10
Outline
•
•
•
•
•
•
•
•
•
•
Expressions and values V
Variables
Functions
Types
Recursion
Datatypes
Pattern matching
Higher-order functions
Exceptions
Modules
13
Variable Declaration
- let x = 1 + 1;;
val x : int = 2
• A variable x is “bound” to value 2.
• From now on, any occurrence of x is replaced by 2.
- let y = x + x;;
val x : int = 4
14
Local Declaration
let x = 1 in
let y = x + x in
let x = y + y in
z + z + x
8
15
Nested Local Declaration
let x = 1 in
x + x
let y = <expression> in
y + y
let y = let x = 1 in x + x in
y + y
16
Why “Local”?
let y = let
x = 1
in
x + x
in
okay???
x + y
17
Variables are NOT variable.
• The contents of a variable never change.
– immutability of variables
• Surprise?
– That’s because you are thinking about variables
in imperative programming.
variables in OCaml
<>
variables in C
18
Then Why Variables?
• Any advantage in using variables at all?
let x = 1 in
let y = x + x in
let z = y + y in
z + z
VS.
((1 + 1) + (1 + 1)) +
((1 + 1) + (1 + 1))
What if it takes 10 hours to evaluate 1?
19
Outline
•
•
•
•
•
•
•
•
•
•
Expressions and values V
Variables V
Functions
Types
Recursion
Datatypes
Pattern matching
Higher-order functions
Exceptions
Modules
20
When is the first time you learned the concept of
function?
21
함수의 사전 정의
• 함수(函數): 두 변수 x, y간에 어떤 관계가 있어 x의
변화에 따라 y가 일정한 법칙으로 변화할 때 y를 x의
함수라 함. (function)
(동아 마스타 국어사전)
22
한자 함
•函
1. 함(함).
2. 편지(함)
3. 갑옷(함)
4. 넣을, 들일(함)
예:
(書函) 서함: 책을 넣는 상자
23
Function = 函數 = Box Number!
24
Using a Box Number
25
Using a Box Number - Generalized
…
…
26
Function in OCaml = Box Number
fun x -> x + 1 n
=
27
Function Application
…
(fun x -> x + 1) n
• We “apply” (fun x -> x + 1) to n.
• x is called a formal argument/parameter.
• n is called an actual argument/parameter.
28
Evaluating a Function Application
…
(fun x -> x + 1) n
n+ 1
…
29
Functions in OCaml
• Nameless function
– fun x -> x + 1;;
• Storing a nameless function to a variable
– let incr = fun x -> x + 1;;
• Function declaration
– let incr x = x + 1;;
30
Function Applications
incr 1
(fun x -> x + 1) 1
1 + 1
2
31
First-Class Stamps
32
First-class Objects
• First-class objects = primitive objects
– can be stored in a variable.
– can be passed as an argument to a function.
– can be returned as a return value of a function.
• Examples:
– integers
– booleans
– characters
– floating-point numbers
–…
33
First-class Objects in C
• First-class objects
– integers
– characters
– floating-point numbers
– pointers
– structures
–…
• Functions?
– Function pointers are first-class objects.
– But functions are not.
• Why? You cannot create new functions on the fly!
34
Functions = First-class Objects in OCaml
• Functions:
– can be passed as an argument to a function.
– can be returned as a return value of a function.
35
Box Number as Output
…
…
such that
…
…
36
Box Number as Output
x
…
…
+x
37
Box Number as Output
x
y
y+x
38
Box Number as Output
x
y
fun y -> y+x
y+x
39
Box Number as Output
x
y
fun y -> y+x
y+x
fun y -> y+x
40
Box Number as Output
x
y
fun x -> (fun y -> y+x)
fun y -> y+x
y+x
fun y -> y+x
41
In OCaml
• Recall the following declarations are equivalent:
– let incr = fun x -> x + 1;;
– let incr x = x + 1;;
• Then:
– let add = fun x -> (fun y -> y + x);
– let add x = fun y -> y + x;
– let add x y = y + x;
• add can take a single argument to return a function.
42
Adding Two Integers
add 1 2
(fun x -> (fun y -> y + x)) 1 2
(fun y -> y + 1) 2
2 + 1
3
43
Box Number as Input
(
true,
false)
44
Box Number as Input
f
fun f -> (f true, f false)
( f
true,
f
false)
45
Outline
•
•
•
•
•
•
•
•
•
•
Expressions and values V
Variables V
Functions V
Types
Recursion
Datatypes
Pattern matching
Higher-order functions
Exceptions
Modules
46
Types
• A type specifies what kind of value a given
expression evaluates to.
– 1 + 1 : int
– true && false : bool
– ’A’ : char
– ”hello” : string
– (1, true) : int * bool
– (1, -1, true) : int * int * bool
– 1.0 : float
– () : unit
47
Type Preservation
Expression : T
Value : T
• An evaluation preserves the type of a given
expression.
48
Example
let x = 1 in
let y = x + x in
let z = y + y in
z + z
: int
8 : int
49
Function Types
• T -> T’
– type of functions:
• taking arguments of type T
• returning values of type T’
• Example:
# let incr = fun
val incr : int ->
# let incr x = x
val incr : int ->
x -> x + 1;;
int = <fun>
+ 1;;
int = <fun>
• Explicit type annotation
# let inc = fun (x:int) -> x + 1;;
val inc : int -> int = <fun>
# let incr (x:int) = x + 1;;
val incr : int -> int = <fun>
50
Type of add
x
fun x -> (fun y -> y+x)
fun y -> y+x
51
Type of add
int
fun x -> (fun y -> y+x)
fun y -> y+x
52
Type of add
int
fun x -> (fun y -> y+x)
int -> int
53
Type of add
int
int -> (int -> int)
int -> int
54
What is the Type?
f
fun f -> (f true, f false)
( f
true,
f
false)
55
f : bool -> int ?
f
: (bool -> int) ->
fn f => (f true, f false)
int * int
( f
true,
f
false)
56
But why is it
f : bool ->
int ?
57
Why not f : bool -> char ?
f
: (bool -> char) ->
fun f -> (f true, f false)
char * char
( f
true,
f
false)
58
Then why not
f :
f :
f :
f :
f :
…
bool
bool
bool
bool
bool
->
->
->
->
->
string ?
int * string ?
unit ?
(int -> int) ?
<crazy type> ?
59
So we need
Polymorphism.
60
What is the Type of
f
?
All we know about f is that
it takes booleans as arguments.
fun f -> (f true, f false)
( f
true,
f
false)
61
All we know about f is that
it takes booleans as arguments.
bool
f
?
62
f : bool -> ?
fun f -> (f true, f false) : (bool -> ?) -> ? * ?
63
f : bool -> 'a
fun f -> (f true, f false) : (bool -> 'a) -> 'a * 'a
• 'a
– type variable
– usually read as alpha
– means 'for any type alpha'
64
Polymorphic Types
• Types involving type variables 'a, 'b, 'c, ...
• E.g.
– fun x -> x :
'a -> 'a
– fun x -> fun y -> (x, y) :
'a -> 'b -> ('a * 'b)
– fun (x : 'a) -> fun (y : 'a) -> x = y :
'a -> 'a -> bool
65
Outline
•
•
•
•
•
•
•
•
•
•
Expressions and values V
Variables V
Functions V
Types V
Recursion
Datatypes
Pattern matching
Higher-order functions
Exceptions
Modules
66
Recursion vs. Iteration
• Recursion in OCaml
let rec 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!
67
Recursion in Action
let rec sum n =
if n = 0 then 0
else sum (n - 1) + n
call stack
0
f 0
f 1
f 9
f 10
further computation
1 + 2
...
...
f 8
0 + 1
36 + 9
45 + 10
55
evaluation
68
Funny Recursion
let rec zero n =
if n = 0 then 0
else zero (n - 1)
call stack
0
f 0
f 1
f 9
f 10
no further computation
0
...
...
f 8
0
0
0
0
evaluation
69
Funny Recursion Optimized
let rec zero n =
if n = 0 then 0
else zero (n - 1)
call stack
0
f 0
f 1
f 9
f 10
0
...
...
f 8
0
0
0
0
evaluation
70
Funny Recursion Further Optimized
let rec 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
71
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!
72
Example
• Non-tail recursive sum
let rec sum n =
if n = 0 then 0
else sum (n - 1) + n
• Tail recursive sum
let rec sum' accum k =
if k = 0 then accum
else
sum' (accum + k) (k - 1)
let sum n = sum' 0 n
• Think about the invariant of sum':
– given:
sum' accum k
– invariant:
accum = n + (n - 1) + ... (k + 1)
73
Outline
•
•
•
•
•
•
•
•
•
•
Expressions and values V
Variables V
Functions V
Types V
Recursion V
Datatypes
Pattern matching
Higher-order functions
Exceptions
Modules
74
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?
75
Datatypes in OCaml
type shape = Circle | Rectangle | Triangle
• No flexibility
– e.g.
Circle + 1
Triangle - 1
Circle + Triangle
(x)
(x)
(x)
• But high safety.
76
Set
type set =
Empty |
Many
# Empty ;;
- : set = Empty
# Many ;;
- : set = Many
77
Set with Arguments
type set =
Empty |
Many of int
# Many 5 ;;
- : set = Many 5
78
Set with Type Parameters
type 'a set =
Empty |
Singleton of 'a |
Pair of 'a * 'a
# Singleton 0;;
- : int set = Singleton 0
# Pair (0, 1);;
- : int set = Pair (0, 1)
79
Set with Type Parameters
type 'a set =
Empty |
Singleton of 'a |
Pair of 'a * 'a
# Pair (Singleton 0, Pair (0, 1)) ;;
- : int set set =
Pair (Singleton 0, Pair (0, 1))
80
Set with Type Parameters
type 'a set =
Empty |
Singleton of 'a |
Pair of 'a * 'a
# Pair (0, true);;
81
Set with Type Parameters
type 'a set =
Empty |
Singleton of 'a |
Pair of 'a * 'a
# Pair (0, true);;
Error: This expression has type bool but an
expression was expected of type
int
82
Recursive Set with Type Parameters
type 'a set =
Empty |
NonEmpty of 'a * 'a set
• This is essentially the definition of datatype list.
83
Datatype list
type 'a list =
[] |
:: of 'a * 'a list
# [] ;;
- : 'a list = []
# 2 :: [] ;;
- : int list = [2]
# [2] ;;
- : int list = [2]
# [1; 2] ;;
- : int list = [1; 2]
# 1 :: 2 :: [] ;;
- : int list = [1; 2]
# 1 :: (2 :: []) ;;
- : int list = [1; 2]
(* defined internally *)
(* infix *)
(* infix *)
(* right associative *)
84
Datatype list
type 'a list =
[] |
:: of 'a * 'a list
(* defined internally *)
(* infix *)
(X)
# 1 :: [2] :: [];;
# [1] :: 2 :: [] ;;
(X)
# [1] :: [2] :: [] ;;
- : int list list = [[1]; [2]]
# [1] :: [[2]] ;;
- : int list list = [[1]; [2]]
85
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?
86
Outline
•
•
•
•
•
•
•
•
•
•
Expressions and values V
Variables V
Functions V
Types V
Recursion V
Datatypes V
Pattern matching
Higher-order functions
Exceptions
Modules
87
Simple Pattern
type shape = Circle | Rectangle | Triangle
(* convertToEnum : shape -> int *)
let convertToEnum (x : shape) : int =
match x with
Circle -> 0
| Rectangle -> 1
| Triangle -> 2
88
Pattern with Arguments
type set =
Empty |
Many of int
let size (x : set) : int =
match x with
Empty -> 0
| Many n -> n
89
Wildcard Pattern _ : "don't care"
type 'a set =
Empty |
Singleton of 'a |
Pair of 'a * 'a
let isEmpty (x : 'a set) : bool =
match x with
Empty -> true
| _ -> false
90
Pattern with Type Annotation
type 'a list =
[] |
:: of 'a * 'a list
(* defined internally *)
(* infix *)
let rec length (x : 'a list) : int =
match x with
([] : 'a list) -> 0
| (_ : 'a) :: (tail : 'a list) ->
1 + length tail
91
Outline
•
•
•
•
•
•
•
•
•
•
Expressions and values V
Variables V
Functions V
Types V
Recursion V
Datatypes V
Pattern matching V
Higher-order functions
Exceptions
Modules
92
Higher-order Functions
• Take functions as arguments.
• Return functions as the result.
93
Why "Higher-order"?
•
•
•
•
•
T0
T1
T2
T3
...
::=
::=
::=
::=
int |
T0 ->
T1 ->
T2 ->
bool
T0 |
T1 |
T2 |
| float
T0
T1
T2
|
(*
(*
(*
unit | ...
1st order *)
2nd order *)
higher order *)
94
Higher-order Functions in List
•
•
•
•
•
val
val
val
val
val
exists : ('a -> bool) -> 'a list -> bool
for_all : ('a -> bool) -> 'a list -> bool
map : ('a -> 'b) -> 'a list -> 'b list
filter : ('a -> bool) -> 'a list -> 'a list
iter : ('a -> unit) -> 'a list -> unit
(* print_int : int -> unit *)
let print_int i =
print_string ((string_of_int i) ^ "\n" );;
List.iter print_int [1; 2; 3];;
95
List Fold Function - Left
• fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
current result
current element
new result
initial result
elements
final result
• fold_left f a0 [b0; b1; b2; ...; bn-1]
b0
b1
a0 f
a1 f
b2
...
bn-2
a2 f a3 ... an-2 f
bn-1
an-1 f
an
96
List Fold Function - Right
• fold_right : (‘b -> ‘a -> ‘a) -> ‘b list -> ‘a -> ‘a
current element
current result
new result
elements
initial result
final result
• fold_right f [b0; b1; b2; ...; bn-1] an
b0
b1
a0 f
a1 f
b2
...
bn-2
a2 f a3 ... an-2 f
bn-1
an-1 f
an
97
Summation
let sum (l : int list) =
(+) a -> a + accum) 0 l
List.fold_left (fun accum
• fold_left (+) 0 [a0; a1; a2; ...; an-1]
a0
0 +
a1
¢
+
¢
a2
...
+
¢ ...
an-2
¢
+
an-1
¢
+

98
List Reversal
let reverse (l : 'a list) =
List.fold_left (fun rev a -> a :: rev) [] l
• Whenever you need iterations over lists,
first consider fold_left and fold_right.
99
More Examples
let exists f l =
List.fold_left (fun a b -> a || f b) false l
let for_all f l =
List.fold_left (fun a b -> a && f b) true l
let map f l =
List.fold_right (fun a b -> f a :: b) l []
let filter f l =
List.fold_right (fun a b ->
if f a then a :: b else b) l []
100
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 OCaml manual.
• Modules
101
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
102
Structures and Signatures
• Structure
– collection of type declarations,
exceptions, values, and so on.
• Signature
– conceptually type of
structures.
module Set =
struct
type 'a set = 'a list
let empty_set = []
let singleton x = [x]
let union s1 s2 = s1 @ s2
end
module type SET =
sig
type 'a set
val empty_set : 'a set
val singleton : 'a -> 'a set
val union :
'a set -> 'a set -> 'a set
end
103
Transparent Constraints
• Type definition is exported to the outside.
module Set =
struct
type 'a set = 'a list
let empty_set = []
let singleton x = [x]
let union s1 s2 = s1 @ s2
end
# Set.singleton 1 = [1] ;;
- : bool = true
104
Opaque Constraints
• No type definition is exported.
module Set : SET =
struct
type 'a set = 'a list
let empty_set = []
let singleton x = [x]
let union s1 s2 = s1 @ s2
end
module type SET =
sig
type 'a set
val empty_set : 'a set
val singleton : 'a -> 'a set
val union :
'a set -> 'a set -> 'a set
end
# Set.singleton 1 = [1] ;;
Error: This expression has type
'a list but an expression was
expected of type int Set.set
105
Overriding Opaque Constraints
• Use the with keyword.
module Set
: SET with
type ‘a set = ‘a list =
struct
type 'a set = 'a list
let empty_set = []
let temp x = [x]
let singleton x = temp x
let union s1 s2 = s1 @ s2
end
module type SET =
sig
type 'a set
val empty_set : 'a set
val singleton : 'a -> 'a set
val union :
'a set -> 'a set -> 'a set
end
# Set.singleton 1 = [1] ;;
- : bool = true
106
Functors
• Functions on structures
– takes a structure as an argument
– returns a structure as the result
structure
structure
• The most powerful tool for structuring programs
• See Assignment #3.
107
For more information on OCAML, visit:
http://caml.inria.fr/pub/docs/manual-ocaml-4.01/
https://realworldocaml.org/
Related documents