Download Slide 1

Document related concepts

Scala (programming language) wikipedia , lookup

Anonymous function wikipedia , lookup

Curry–Howard correspondence wikipedia , lookup

Lambda calculus definition wikipedia , lookup

Currying wikipedia , lookup

Falcon (programming language) wikipedia , lookup

Closure (computer programming) wikipedia , lookup

Tail call wikipedia , lookup

Lambda lifting wikipedia , lookup

Intuitionistic type theory wikipedia , lookup

C Sharp (programming language) wikipedia , lookup

Standard ML wikipedia , lookup

Transcript
Programming Languages
Introduction to
Functional Programming
임현승
Kangwon National University
These slides were originally created by Prof. Sungwoo Park at POSTECH.
Programming Paradigms
• Paradigm: In science, a paradigm describes distinct concepts
or thought patterns in some scientific discipline.
• Main programming paradigms
– Imperative programming: C, Pascal, …
– Logic programming: Prolog, …
– Functional programming: SML, Haskell, OCaml, Lisp,
Scheme, F#, …
• Orthogonal concept:
– Object-oriented programming: C++, Java, OCaml, …
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 y : int = 4
14
Local Declaration
let
let
let
z +
x = 1 in
y = x + x in
z = y + y in
z
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
okay???
in
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
let
let
z +
x = 1 in
y = x + x in
z = y + y in
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
함수의 사전 정의
• 함수 [function, 函數]: 변수 x와 y 사이에 x의 값이
정해지면 따라서 y값이 정해진다는 관계가 있을 때,
y는 x의 함수라고 한다.
(두산백과)
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
=
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 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
let
let
z +
x = 1 in
y = x + x in
z = y + y in
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
val incr :
# let incr
val incr :
= fun x -> x + 1;;
int -> int = <fun>
x = x + 1;;
int -> int = <fun>
• Explicit type annotation
# let incr = fun (x:int) -> x + 1;;
val incr : 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)
fun 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
• Poly = many
• Morphism = forms/shapes
• Polymorphic function = a function that can be
applied to values of different types
• E.g., C++ templates,
Java generics
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, ...
• 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
• Iteration in C
let rec sum n =
if n = 0 then 0
else sum (n - 1) + n
int i = 0, sum = 0;
for (; i <= n; i++)
sum += i;
• 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
• Tail recursive sum
let rec sum n =
if n = 0 then 0
else sum (n - 1) + n
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
(x)
Triangle - 1
(x)
Circle + Triangle (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 =
[] |
(* defined internally *)
:: of 'a * 'a list
(* infix *)
#
#
#
#
-
1 :: [2] :: [];;
(X)
[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 =
[] |
(* defined internally *)
:: of 'a * 'a list
(* 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 ::= int | bool | float | unit | ...
• T1 ::= T0 -> T0 | T0
(* 1st order *)
• T2 ::= T1 -> T1 | T1
(* 2nd order *)
• T3 ::= T2 -> T2 | T2
(* 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
bn-1
a2 f a3... an-2 f 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
bn-1
a2 f a3... an-2 f an-1 f
an
97
Summation
let sum (l : int list) =
(+)-> a + accum) 0 l
List.fold_left (fun accum a
• 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
Modules
101
Exception
• To signal and handle exceptional conditions
• Non-local control structures (e.g., goto in C)
• Exception declaration
# exception Empty_list;;
exception Empty_list
• Exceptions are used throughout the standard library to
signal cases where the library functions cannot
complete normally.
102
Signaling the exception
• With the raise operator
• e.g., a function for taking the head of a list
# let head l =
match l with
[] -> raise Empty_list
| hd :: tl -> hd;;
val head : 'a list -> 'a = <fun>
# head [1;2];;
- : int = 1
# head [];;
Exception: Empty_list
103
Catching the exception
• Exceptions can be trapped with the try … with construct.
• The with part is a regular pattern-matching on the exception value.
# let print_head_list l =
try print_string (head l ^ “\n”)
with Empty_list -> print_string “Empty_list\n”
val print_head_list : string list -> unit = <fun>
# print_head_list [“abc”, “def”];;
abc
- : unit = ()
# print_head_list [];;
Empty_list
- : unit = ()
104
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
105
Structures and Signatures
• Structure
– collection of type declarations,
exceptions, values, and so on.
– Structures a program and
provides a new namespace
module Set =
struct
type 'a set = 'a list
let empty_set = []
let singleton x = [x]
• Signature
– conceptually type of
structures.
module type SET =
sig
type 'a set
val empty_set : 'a set
val singleton : 'a -> 'a set
val union :
let union s1 s2 = s1 @ s2
end
'a set -> 'a set -> 'a set
end
106
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
107
If you’re a library developer
• What if you later improve your implementation using a
binary search tree instead of a list?
module Set =
(* your library code *)
struct
type 'a set = 'a bst
let empty_set = ...
let singleton x = ...
...
End
(* library user’s code *)
# Set.singleton 1 = [1] ;;
Error: This expression has type 'a list but an
expression was expected of type int bst
108
Opaque Constraints
• No type definition is exported (Information hiding)
module Set : SET =
module type SET =
struct
sig
type 'a set = 'a list
type 'a set
let empty_set = []
val empty_set : 'a set
let singleton x = [x]
val singleton : 'a -> 'a set
let union s1 s2 = s1 @ s2
val union :
end
'a set -> 'a set -> 'a set
end
# Set.singleton 1 = [1] ;;
Error: This expression has
type int list but an
expression was expected
of type int Set.set
109
Overriding Opaque Constraints
• Use the with keyword.
• Furthermore, only definitions specified in the signature are
exported to outside.
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
110
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
111
Code Reuse by Functors
Int
String
Functors
Float
User
defined
type
Variation points
(Set elements)
Reusable code
(Set operations)
Int Set
String Set
Set for user
Float Set defined type
Functor applications
(Set implementations)
112
Generic Set Functor
• Code reuse using a functor
• Ex. Different set implementations w.r.t. the type of set elements
# type comparison = LESS | Equal | Greater
# module type ORDERED = sig
type t
val compare : t -> t -> comparison
end
# module Set =
functor (Elt : ORDERED) ->
(* functor declaration *)
struct
type elem = Elt.t
type set = elem list
let empty = []
...
end
# module OrderedString = struct type t = string ... end
# module StringSet = Set(OrderedString) (* functor application *)
# module OrderedADT = struct type t = user_defined_t ... end
# module ADTSet = Set(OrderedADT)
(* functor application *)
...
113
For more information on OCaml, visit:
http://caml.inria.fr/pub/docs/manual-ocaml/index.html
https://realworldocaml.org/
http://ocaml.org
Reading Assignment
• Notes on Programming Languages 1장, 2장 읽기
• If you’re comfortable with English,
Read POSTECH PL Course Note Chapters 1-2
115