410 likes | 679 Views
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
E N D
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
States Pure function Impure function with assignment Computation • Achieved via function application • Functions are mathematical functions without side-effects. • Output is solely dependent of input.
Outline • What is Functional Programming? • Basic Expressions • Using Higher-order Functions • List Processing • Value and Type Constructions
Basic SML Expressions <Exp> ::= <Constants> | <Identifiers> | <Exp1> <op> <Exp2> | | if <Exp0> then <Exp1> else <Exp2> | let {<Decl>}in <Exp> end | fn <Pattern>{<Pattern>} => <Exp> | <Exp1> <Exp2> | (<Exp1>, <Exp2> {, <Exp3>}) | <List-Exp> <Constants> ::= all constants <Identifiers> ::= all identifiers <op> ::= all binary operators
If-expression, Not If-statement if <e0> then <e1> else <e2> if (3 > 0) then 4+x else x-4 ; 4+x If-expression evaluates to a value.
Constructing a Linear List <List-Exp> ::=[[<Exp> {, <Exp>}] ] | nil | <Exp> :: <Exp> nil ; 1::nil; 1::(2::nil); (x+2)::(y-3)::(x*3)::nil ; Note : A list must end with nil.
tail Constructing a Linear List <List-Exp> ::=[[<Exp> {, <Exp>}] ] | nil | <Exp> :: <Exp> nil ; 1::nil; 1::(2::nil); (x+2)::(y-3)::(x*3)::nil ; Operator :: is right associative. head [] ; [1]; [1,2]; [x+2,y-3,x*3] ;
Constructing a Tuple (<Exp> , <Exp> {, <Exp>}) Tuple is like a record without field names. (1,2) ; (1,2,True,4,False); (x+2,y=3,x*3) ;
Giving An Expression A Name Declaring an expression with a name enables easy reference. <decl> ::= val <pattern>= <exp> Identifiers are legally declared after proper pattern matching. val x = 3 ; val (y,z) = (x+3,x-3) ; val [a,b] = [x+2,y-3] ; val [a,b] = [x+2] ; val (x::xs) = [1,2,3,4,5] ;
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] ; Pattern-Match a List
Local Declaration/Definition let {<decl>}in <exp>end let val x = (3,4) val (a,b) = x in a + 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 <Decl> ::= fun <var><para> = <exp> <para> ::= <pattern>{<pattern>} funfac x=if (x > 0) then x * (fac (x-1)) else 1 fac 2if (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. <Decl> ::= fun <var><para>= <exp> {| <var><para> = <exp>} funfac 0=1 |fac n=n * (fac (n-1)) Function application is accomplished via pattern matching. fac 2 2 * (fac (2-1)) 2 * (fac 1) 2 * (1 * (fac (1-1))) 2 * (1 * (fac 0)) 2 * (1 * 1) 2
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<para> => <Exp> (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 ; choose(a = b,fn x => x*2, fac)(4) returns either 8 or 24 fun compose (f,g) = fn x => f (g x) (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 • fun factorial (x) = if (x <= 1) then 1 • else x * factorial (x-1) ; • Mutual-Recursive functions • funeven(0)=true • |even(1)=false • |even(x)=odd(x-1) • andodd(x) =even(x-1) ;
a pair pattern 2 pattern 1 Passing Arguments to a Function How many argument does this function really take? fun f (x,y) = x + 2 * y ; Calling f with argument (1,2) yields 5. fun g x y = x + 2 * y ; 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]) ==> 1 + 1 + length([10]) ==> 1 + 1 + 1 + length([]) ==> 1 + 1 + 1 + 0 ==> 3 Note how a list is being consumedfrom 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 x@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 fun map f [] = [] | map f (x::xs) = (f x) :: (map f xs) Law for Map : map f (map g list) = map (f o g) list map f (map g [a1,..,an]) = map f [g a1,..,g an] = [f (g a1),.., f (g an)] = [(f o g) a1,.., (f o g) an] = map (f o g) [a1,..an]
: a1 a1 : a2 a2 : : an a0 an [] Reduce Operation reduce [a1,..,an] a0 = a1 (a2 (.. (an a0))) reduce f [a1,..,an] a0 = f(a1,f(a2,f(..,f(an,a0))))
+ : 1 + 2 : 1 + 4 : 1 0 6 [] 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
Outline • What is Functional Programming? • Basic Expressions • Using Higher-order Functions • List Processing • Value and Type Constructions
Types: Classification of Values and Their Operators Basic Types TypeValuesOperations bool true,false =, <>, … int …,~1,0,1,2,… =,<>,<,+,div,… real ..,0.0,.,3.14,.. =,<>,<,+,/,… string “foo”,”\”q\””,… =,<>,… Boolean Operations: e1 andalsoe2 e1 orelsee2
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 infersit 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. • <type-expr> ::= <type-name> | <type-constant> • | <type-expr>*<type-expr> • | <type-expr><type-expr> • | <type-expr>list • | …
Type of a Tuple (1,2) : int * int (3.14159, x+3,true) : real * int * bool A * B = set of ordered pairs (a,b) DataConstructor : ( , ) as in (a,b) TypeConstructor :*as in A * B In general, (a1,a2,…,an) belongs to A1*A2*…*An.
Type of A List Type Constructor : list [1,2,3] : int list [3.14, 2.414] : real list [1, true, 3.14] : ?? Not well-typed!! Alist= set of all lists of A -typed values. 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],…
Function TypesDeclaring domain & co-domain fac : int -> int A -> B= set of all functions from Ato B. 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
Sum of Types Enumerated Types datatypeDays=Mo|Tu|We|Th|Fr|Sa|Su; New Type data / data constructors • Selecting a summand via pattern matching: • cased • ofSa => “Go to cinema” • |Su => “Extra Curriculum” • |_ => “Life goes on”
Combining Sum and Product of Types: Algebraic Data Types Defining an integer binary tree: datatypeIntTree=Leafint| Nodeof(IntTree, int, IntTree); fun height (Leaf x) = 0 | height (Node(t1,n,t2))= 1 + max(height(t1),height(t2)) ;
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.