CS 2104 : Prog. Lang. Concepts. Functional Programming I Lecturer : Dr. Abhik Roychoudhury School of Computing From Dr. Khoo Siau Cheng’s lecture notes
Outline What is Functional Programming? Basic Expressions Using Higher-order Functions List Processing Value and Type Constructions
Features of Functional Programming Expressions: The main construct in the language Functions : First-class citizens of the language Types : for specification and verification List Processing
Computation Achieved via function application Functions are mathematical functions without side-effects. –Output is solely dependent of input. Pure function States Impure function with assignment
Outline What is Functional Programming? Basic Expressions Using Higher-order Functions List Processing Value and Type Constructions
Basic SML Expressions ::= | | | | if then else | let { } in end | fn { } => | | (, {, }) | ::= all constants ::= all identifiers ::= all binary operators
If-expression, Not If-statement if then else if (3 > 0) then 4+x else x-4 ; 4+x If-expression evaluates to a value.
Constructing a Linear List ::=[[ {, }] ] | nil | :: nil ; 1::nil ; 1::(2::nil); (x+2)::(y-3)::(x*3)::nil ; Note : A list must end with nil.
Constructing a Linear List [] ; [1] ; [1,2]; [x+2,y-3,x*3] ; ::=[[ {, }] ] | nil | :: nil ; 1::nil ; 1::(2::nil); (x+2)::(y-3)::(x*3)::nil ; Operator :: is right associative. head tail
Constructing a Tuple (1,2) ; (1,2,True,4,False) ; (x+2,y=3,x*3) ; (, {, }) Tuple is like a record without field names.
Giving An Expression A Name Declaring an expression with a name enables easy reference. val x = 3 ; val (y,z) = (x+3,x-3) ; val [a,b] = [x+2,y-3] ; ::= val = Identifiers are legally declared after proper pattern matching. val [a,b] = [x+2] ; val (x::xs) = [1,2,3,4,5] ;
Pattern-Match a List val (x::xs) = [1,2,3,4,5] ; x 1 xs [2,3,4,5] ; val (x::_::y::xs) = [1,2,3,4,5] ; x 1 y 3 xs [4,5] ;
Local Declaration/Definition let { } in end letval x = (3,4) val (a,b) = x ina + a * b end ; 15 Identifiers are statically scoped
Nested bindings of same var. Let val x =2 in let val x = x +1 in x*x end end Let val x = 2 in let val y = x +1 in y * y end end Let val x = 2 in (x+1)*(x+1) end 9
Function Declaration and Function Application fun fac x = if (x > 0) then x * (fac (x-1)) else 1 ::= fun = ::= { } fac 2 if (2 > 0) then 2 * (fac (2-1)) else 1 2 * (fac 1) 2 * (if (1 > 0) then 1 * (fac (1-1)) else 1) 2 * (1 * (fac 0)) 2 * (1 * 1) 2
Function as Equations A function can be defined by a set of equations. fun fac 0 = 1 | fac n = n * (fac (n-1)) ::= fun = {| = } fac 2 2 * (fac (2-1)) 2 * (fac 1) 2 * (1 * (fac (1-1))) 2 * (1 * (fac 0)) 2 * (1 * 1) 2 Function application is accomplished via pattern matching.
Outline What is Functional Programming? Basic Expressions Using Higher-order Functions List Processing Value and Type Constructions
Functions as First-Class Citizens Lambda abstraction:A nameless function fn => (fn (x,y) => x + y) (2,3) 2+3 5 Definition Application val newfn = fn (x,y) => x + y ; newfn(2,4) + newfn(4,3)
Functions as First-Class Citizens Passing function as argument fun apply (f, x) = f x apply (fac, 3) fac 3 6 apply (fn x => x*2, 3) (fn x => x*2) 3 3*2 6
Functions as First-Class Citizens Returning function as result fun choose (x,f,g) = if x then f else g ; fun compose (f,g) = fn x => f (g x) choose(a = b,fn x => x*2, fac)(4) returns either 8 or 24 (compose (add3,fac)) 4 (fn x => add3 (fac x))(4) (add3 (fac 4)) 27 compose (f,g) is denoted as f o g
Functions as First-Class Citizens Storing function in data structure val flist = [ fac, fib, add3] ; let val [f1,f2,f3] = flist in (f1 2) + (f2 3) + (f3 4) end ;
Functions as Algorithms A function describes a way for computation. Self-Recursive function funfactorial (x) = if (x <= 1) then 1 else x * factorial (x-1) ; Mutual-Recursive functions fun even(0) = true | even(1) = false | even(x) = odd(x-1) and odd(x)= even(x-1) ;
Passing Arguments to a Function How many argument does this function really take? fun f (x,y) = x + 2 * y ; a pair fun g x y = x + 2 * y ; pattern 1 pattern 2 Calling f with argument (1,2) yields 5. Calling g with arguments 1 and 2 yields 5.
Outline What is Functional Programming? Basic Expressions Using Higher-order Functions List Processing Value and Type Constructions
Exploring a List fun length [] = 0 | length (x::xs) = 1 + length(xs) ; length([10,10,10]) ==> 1 + length([10,10]) ==> length([10]) ==> length([]) ==> ==> 3 Note how a list is being consumed from head to tail.
fun append([],ys) = ys | append(x::xs,ys) = x :: append(xs,ys); append([1,2],[3]) ==> 1::append([2],[3]) ==>1::2::append([],[3]) ==>1::2::[3] ==>[1,2,3] Note how a new list is being produced from head to tail. append(x,y) is denoted by y.
fun rev(xs) = let fun r([],ys) = ys | r(x::xs,ys)= r(xs,x::ys) in r(xs,[])end rev([1,2,3]) ==> r([1,2,3],[]) ==> r([2,3],1::[]) ==> r([3],2::1::[]) ==> r([],3::2::1::[]) ==> [3,2,1] Note how lists are being produced and consumed concurrently.
Map operation map square [1,2,3,4] ==> [square 1, square 2,.., square 4] ==> [1,4,9,16] fun map f [] = [] | map f (x::xs) = (f x) :: (map f xs) map square [1,2] ==> (square 1) :: (map square [2]) ==> 1 :: (square 2) :: (map square []) ==> 1 :: 4 :: [] == [1,4]
Map operation Law for Map : map f (map g list) = map (f o g) list map f (map g [a 1,..,a n ]) = map f [g a 1,..,g a n ] = [f (g a 1 ),.., f (g a n )] = [(f o g) a 1,.., (f o g) a n ] = map (f o g) [a 1,..a n ] fun map f [] = [] | map f (x::xs) = (f x) :: (map f xs)
Reduce Operation reduce [a 1,..,a n ] a 0 = a 1 (a 2 (.. (a n a 0 ))) reduce f [a 1,..,a n ] a 0 = f(a 1,f(a 2,f(..,f(a n,a 0 )))) : a1a1 : a2a2 : : anan [] a1a1 a2a2 anan a0a0
reduce (op *) [2,4,6] 1 ==> 2 * (4 * (6 * 1)) ==> 48 reduce (fn (x,y)=>1+y) [2,4,6] 0 ==> 1 + (1 + (1 + 0)) ==> 3 [] : 2: 4:
Outline What is Functional Programming? Basic Expressions Using Higher-order Functions List Processing Value and Type Constructions
Types: Classification of Values and Their Operators TypeValuesOperations booltrue,false=, <>, … int…,~1,0,1,2,…=,<>,<,+,div,… real..,0.0,.,3.14,..=,<>,<,+,/,… string“foo”,”\”q\””,…=,<>,… Basic Types Boolean Operations: e 1 andalso e 2 e 1 orelse e 2
Types in ML Every expression used in a program must be well- typed. –It is typable by the ML Type system. Declaring a type : 3 : int [1,2] : int list Usually, there is no need to declare the type in your program – ML infers it for you.
Structured Types Structured Types consist of structured values. Structured values are built up through expressions. Eg : (2+3, square 3) Structured types are denoted by type expressions. ::= | | * | | list | …
Type of a Tuple A * B= set of ordered pairs (a,b) DataConstructor: (, )as in (a,b) Type Constructor :*as in A * B In general, (a 1,a 2,…,a n )belongs to A 1 *A 2 *…*A n. (1,2) : int * int ( , x+3,true) : real * int * bool
Type of A List [1,2,3] : int list [3.14, 2.414] : real list [1, true, 3.14] : ?? Type Constructor :list A in A-list refers to any types: (int*int) list: [ ], [(1,3)], [(3,3),(2,1)], … int list list: [ ], [[1,2]], [[1],[0,1,2],[2,3],… A list= set of all lists of A -typed values. Not well-typed!!
fac : int -> int Function Types Declaring domain & co-domain Type Constructor : -> Data Construction via : 1. Function declaration : fun f x = x + 1 ; 2. Lambda abstraction : fn x => x + 1; Value Selection via function application: f 3 4 (fn x => x + 1) 3 4 A -> B = set of all functions from A to B.
datatype Days = Mo | Tu | We | Th | Fr | Sa | Su ; Selecting a summand via pattern matching: case d ofSa => “Go to cinema” |Su => “Extra Curriculum” |_ => “Life goes on” Sum of Types Enumerated Types New Type data / data constructors
Defining an integer binary tree: datatype IntTree = Leaf int | Node of (IntTree, int, IntTree) ; fun height (Leaf x) = 0 | height (Node(t1,n,t2))= 1 + max(height(t1),height(t2)) ; Combining Sum and Product of Types: Algebraic Data Types
Conclusion A functional program consists of an expression, not a sequence of statements. Higher-order functions are first-class citizen in the language. –It can be nameless List processing is convenient and expressive In ML, every expression must be well-typed. Algebraic data types empowers the language.