490 likes | 642 Views
CSC4504 : Formal Languages & Applications J Paul Gibson, A207 paul.gibson@int-edu.eu http://www-public. it-sudparis.eu /~ gibson/Teaching/CSC4504/. Functional Programming http://www-public.it-sudparis.eu/~ gibson/Teaching/CSC4504/L1-Functional.pdf.
E N D
CSC4504 : FormalLanguages & Applications J Paul Gibson, A207 paul.gibson@int-edu.eu http://www-public.it-sudparis.eu/~gibson/Teaching/CSC4504/ FunctionalProgramming http://www-public.it-sudparis.eu/~gibson/Teaching/CSC4504/L1-Functional.pdf TSP: Software Engineering
FunctionalProgramming : a short history You shouldalready know about this … A simple universal computer 1930 s - Lambda Calculus: Alonzo Church, Untyped and SimplyTyped 1950s - Lisp : John McCarthy Scheme (1970s), Common Lisp (1980s) and Dylan (1990s) IPL : Newell, Saw and Simon 1960s - APL : Kenneth Iverson 1970s – FP : John Backus, ML : Robin Milner Miranda (1985), Standard ML (1990), Caml (1985), Ocaml (1996) 1980s – Clean : RadboudUniversityNijmegen Erlang : Ericsson 1990s – Haskell : Committee (but major Scottish/Glasgow influence/contribution) More recently, languagessupportingfunctional style: Clojure, Scala, F#, Python TSP: Software Engineering
Lambda Calculus Simple Grammar <Exp> ::= <ident> | <constant> | lambda <ident> . <Exp> | -- function abstraction <Exp> <Exp> | -- function application ( <Exp> ) Booleans can be defined; eg: TRUE = lambda a. lambda b. a, FALSE = lambda a. lambda b. b TSP: Software Engineering
Lambda Calculus Simple Grammar <Exp> ::= <ident> | <constant> | lambda <ident> . <Exp> | -- function abstraction <Exp> <Exp> | -- function application ( <Exp> ) Naturals can be defined; eg: ZERO = lambda s. lambda z. z, ONE = lambda s. lambda z. s(z), TWO = lambda s. lambda z. s(s(z)), THREE= lambda s. lambda z. s(s(s(z))), PLUS = lambda x. lambda y. lambda s. lambda z. x s (y s z), TSP: Software Engineering
Lambda Calculus Simple Grammar <Exp> ::= <ident> | <constant> | lambda <ident> . <Exp> | -- function abstraction <Exp> <Exp> | -- function application ( <Exp> ) Recursive or self-referential definitions are not needed to write a recursive function in lambda calculus! The function Y gives the effect of recursion. Y is known as the paradoxical operator or as the fixed-point operator. Y = lambda G. (lambda g. G(g g)) (lambda g. G(g g)) TSP: Software Engineering
FunctionalProgramming : key concepts • Semanticsbuilt on lambda calculus • First-class/higher-orderfunctions: no restrictions on use/ functions as parameters (arguments and results) • Pure functions - no sideeffects, but introducesdifferent issues for managing state • Recursion – for iteration • Possibility of non-strict evaluation • Possibility of Type Inference TSP: Software Engineering
Functional Programming (with Caml) • Created in January 1996. • Contact the author: Pierre.Weis@inria.fr • Caml is: • a programming language, • easy to learn, • easy to use, and • amazingly powerful. • It is developed and distributed by INRIA (the main French research institute for computer science. It is freely available for Unix, PC or Macintosh. • There exist two flavors of Caml: • Caml Light is merely a subset of Objective Caml, especially designed for teaching and learning the art of programming • Objective Caml features a powerful modules system, full support to object-oriented paradigm, and an optimizing compiler. TSP: Software Engineering CSC4504/Functional.7
Safety • Caml is a safe language. • The compiler performs many sanity checks on programs before compilation. • Many programming errors cannot happen in Caml: data type confusion such as erroneous access into compound values becomes just about impossible. • All these aspects are carefully verified by the compiler, so that the data access is delegated to the compiler code generator: the perfect integrity of data manipulated by programs is granted for free ! • Caml is statically type-checked --- there is no need to add type information in programs: type annotations are fully automatic and handled by the compiler. TSP: Software Engineering
Data Types • Numerous data types are predefined in Caml: • basic types: integers, floating point numbers, booleans, characters, strings. • more sophisticated data types: tuples, arrays, lists, sets, hash tables, • Caml also offers powerful means to define new data types: • records, enumerated types, and sum types. • Sum types can be thought as a generalization of union data types. They allow unrestricted definitions of heterogeneous values. • As desired, these types can be defined concretely (data constructors are available from outside the module) or abstractly (this implementation is restricted to the defining module, and the data constructors are not accessible from outside the module). • This provides a great fine tuning mechanism over data encapsulation,which is mandatory for programming in the large. TSP: Software Engineering
Functions • Caml is a functional programming language: • there are no restrictions in the definition and use of functions, • they can be passed as arguments or returned as values. TSP: Software Engineering
Automatic memory management • Caml features automatic memory management: • allocation and deallocation of data structures is kept implicit (there is no ``new'' or ``free'' primitives), and • handled by the compiler. • This way programs are much safer, since spurious memory corruption can never occur. • Moreover the memory manager works in parallel with the application, so that there is no noticeable interruption of the Caml program when the garbage collector is running. • Garbage collection is incremental TSP: Software Engineering
Imperative features • Caml provides full imperative capabilities, including updatable arrays, imperative variables and records with mutable fields. • Modules • Caml provides batch compilation, and separate compilation is obtained via the module system. The Caml Light compiler generates executable programs that are both small and portable. • Interactivity • Caml provides an interactive toplevel ``read-eval-print'' loop, that is convenient for both learning and debugging: there is no need to use files, nor add printing routines to get results. • Symbolic capabilities • Caml features pattern matching: it provides a concise, simple, and elegant ``test and bind'' facility for symbolic computation. Other Aspects TSP: Software Engineering
Other aspects continued... • Error recovery • Caml has a general exception mechanism to handle or recover from errors or exceptional situations. • Polymorphism • Caml features ``polymorphic typing'': some types may be left unspecified, standing for ``any type''. That way, functions and procedures that are general purpose may be applied to any kind of data, regardless of their types (e.g. sorting routines may be applied to any kind of arrays). • Evaluation regime • Caml is a strict language, as opposed to lazy ones. However, first order value functions allows the manipulation of delayed expressions, and thus lazy evaluation of potentially infinite data structures is still possible. TSP: Software Engineering
Elementary functions • Using the interactive system, I define the square function, and the recursive factorial function. Then I try my new functions with some examples: • > Caml Light version 0.74 • #let square (x) = x * x;; • square : int -> int = <fun> • #let rec fact (x) = • if x <= 1 then 1 else x * fact (x - 1);; • fact : int -> int = <fun> • #fact (5);; • - : int = 120 • #square (120);; • - : int = 14400 TSP: Software Engineering
The Caml Tool • When you start to use Caml, I recommend the following: • 1) Choose Standard Display • 2) In preferences, • send to Caml on CTRL RETURN • newline on RETURN or ENTER • 3) Keep a text editor open in another window in order to cut and paste code that works as required into a saveable file --- normally the history window should be used for this, but I find it easier to control the saves myself within another editor file. • 4) Try it out .. It is very easy TSP: Software Engineering
Caml Light running under Windows TSP: Software Engineering
Lists • Lists are already built into the Caml language: • [ ] is an empty list of any type of element • a:: [ ] is the list with element a appended on the front of an empty list • [a] is the same as a::[ ] • the type of the list [element] is an a’ list, where a’ is the type of element • the type of the list [12] is an int list • 3::4::5::[ ] is the same as [3;4;5] • we can join lists --- [3;4]@[5;6] = [3;4;5;6] TSP: Software Engineering
Polymorphism: empty lists Testing if a list is empty is very important: let empty = function [] -> true | a::b -> false;; empty [];; # -: bool = true • Note: • the pattern matching • the universal polymorphism (generic list) • Question: evaluate empty [1;2;3] empty : 'a list -> bool = <fun> TSP: Software Engineering
I seeresultshere All mypreviouswork I write code here TSP: Software Engineering
More List Functions Finding the length of a list (the number of elements) --- let rec length = function [] -> 0 | a::b -> (1 + length b);; Note: the function is recursive #length : 'a list -> int = <fun> length [ ];; #- : int = 0 Question: evaluate length [1;2;3;4] TSP: Software Engineering
Polymorphism: sorting lists Insertion sort is defined with two recursive routines, using pattern matching on lists. • #let rec sort = function • | [] -> [] • | x :: l -> insert x (sort l) • and insert elem = function • | [] -> [elem] • | x :: l -> if elem < x then elem :: x :: l • else x :: insert elem l;; • sort : 'a list -> 'a list = <fun> • insert : 'a -> 'a list -> 'a list = <fun> TSP: Software Engineering
Polymorphism: sorting lists Now we can test the sort • #sort [2; 1; 0];; • - : int list = [0; 1; 2] • #sort ["yes"; "ok"; "sure"; "ya"; "yep"];; • - : string list = ["ok"; "sure"; "ya"; "yep"; "yes"] TSP: Software Engineering
A list invariant A useful invariant property for a list is if it is ordered: let rec ordered = function [] -> true | [a] -> true | a::b::c -> (a<b) & (ordered (b::c));; ordered : 'a list -> bool = <fun> Note: this depends on a comparison operator < being defined on the list element types. Thus, ordered depends on constrained polymorphism. TSP: Software Engineering
Searching a list let recis_element = function element -> function [] -> false | a::b -> a = element or is_element element b;; #is_element : 'a -> 'a list -> bool = <fun> Note: the strange way of (seemingly) passing more than 1 parameter to a function! We will come back to currying later TSP: Software Engineering
Caml --- beyond lists • In Caml we also have Cartesian products built in to the language: • tuples: pairs, triples, quadruples, … • (1,2,3) ---- a triple of ints --- • int*int*int • (“P Gibson”, 4597) --- a name and number --- • string*int • ([3;5;4], “a list”,’b’) --- a list of ints and a string and a char --- • int list*string*char • ( [(2,3); (3;5)], [ ] ) --- a list of int pairs and an empty list --- • (int*int)list * a’ list Note: tuples are separated by commas, list elements by semicolons TSP: Software Engineering
Some simple functions on tuples: let first = function (x,y) -> x;; let second = function (x,y) -> y;; first : 'a * 'b -> 'a = <fun> second : 'a * 'b -> 'b = <fun> let max = function (x,y) -> if x< y then y else x;; max : 'a * 'a -> 'a = <fun> let reflect = function (x,y) -> (y,x);; reflect : 'a * 'b -> 'b * 'a = <fun> TSP: Software Engineering
Using tuples with lists • The telephone directory problem: • We wish to store a list of names and telephone numbers in a directory. • We wish to be able to: • add a name and number • remove a name • find the number of a given name Question: how could we use tuples and lists to structure the data in the problem? TSP: Software Engineering
Telephone Directory in Caml --- the data structure • The best way to start is to write out a few Caml expressions for representing a selection of directories: • An empty directory : [ ] • A directory with 1 name and 1 number: [(“paul”, 3)] • A directory with 2 entries: [(“paul”,3); (“james”,4)] • Now, try and spot a pattern and define the required type: • (string * int) list TSP: Software Engineering
Telephone Directory in Caml --- the data structure Product type definition: type directoryEntry = {Name: string; Number: int};; let PaulsNumber = {Name = "Paul"; Number= 111};; Type directoryEntry defined. #PaulsNumber : directoryEntry = {Name = "Paul"; Number = 111} let name_of = function {Name =n; Number = _} -> n;; name_ofPaulsNumber;; name_of : directoryEntry -> string = <fun> #- : string = "Paul" PaulsNumber.Name;; #- : string = "Paul" TSP: Software Engineering
Telephone Directory in Caml --- the data structure let PaulsNumber = {Name = "Paul"; Number= 111};; let PetesNumber = {Name = “Pete"; Number= 111};; let directory = [PaulsNumber; PetesNumber];; Type directoryEntry defined. #PaulsNumber : directoryEntry = {Name = "Paul"; Number = 111} #PetesNumber : directoryEntry = {Name = “Pete"; Number = 111} #directory : directoryEntry list = [{Name = "Paul"; Number = 111}; {Name = “Pete"; Number = 111}] TSP: Software Engineering
Parameterizedproduct types (and) • type ('a,'b) pair = {Fst: 'a; Snd:'b};; • Type pair defined. • Warning: the pair type is similar to the Camlcartesian product *, but it is a different type. • let pair2 = {Fst = `a`; Snd = 1};; • pair2 : (char, int) pair = {Fst = `a`; Snd = 1} • let pair3 = (`a`, 1);; • pair3 : char * int = `a`, 1 TSP: Software Engineering
Definingsum types (or) #type suit = Heart | Diamond | Club | Spade;; Type suit defined. type card = Ace of suit | King of suit | Queen of suit | Jack of suit | Plain of suit * int;; #Type card defined. TSP: Software Engineering
Telephone Directory Functions • let add = function (element, list) -> element::list;; • add : 'a * 'a list -> 'a list = <fun> • let rec search = function (name, [ ] ) -> 0 • | (name, head::tail) -> if name = first(head) • then second (head) • else search(name, tail);; • search : 'a * ('a * int) list -> int = <fun> • let rec remove = function (name, [ ]) -> [ ] • | (name, head::tail) -> if name = first(head) • then tail • else head:: remove(name,tail);; • remove : 'a * ('a * 'b) list -> ('a * 'b) list = <fun> TSP: Software Engineering
Telephone Directory Analysis • Question: does this program implement a TD as you would hope? • Consider the following problems: • we can have a directory in which the 1 name has 2 numbers -- • [(“paul”,1); (“paul,2)] • we can have a directory in which 2 names have the same number --- • [(“paul”,1); (“john”,1)] • Question: how can we exclude these cases? Answer: write an invariant function which takes a telephone directory and returns true if it is well-defined and false otherwise TSP: Software Engineering
Telephone Directory Invariant: an overview • Programming with invariants is a very difficult and advanced skill • It is very important in the goal of achieving correct software (in all programming paradigms) • There are 3problems --- • finding the invariant • coding the invariant • ensuring the invariant Question: can you write the invariant function Inv? TSP: Software Engineering
Ensuring the invariant • Assume that we have the invariant property defined as a boolean function, we must now consider how to guarantee that it is never broken: • All operations on telephone directories must preserve the invariant • If the invariant is true before the operation is carried out then it must be true after the operations is carried out. • Question: which of the operations can break the TD invariant --- • add? • remove? • search? Question: how could you change the code to ensure the invariant? TSP: Software Engineering
Correcting the add operation Previously, we defined add using a generic add operator: let add = function (element, list) -> element::list;; • Now we should write an add operator specific to TDS: • let addtoTD = function (entry, TD ) -> • if inv(add(entry,TD)) then add(entry,TD) • else TD;; • This can be re-written (using a temporary variable) as: • let addtoTD = function (entry, TD ) -> • let x = add(entry,TD) in • if inv(x) then x else TD;; Question: why re-write ?? TSP: Software Engineering
Curried Functions:Let’s spice it up! Consider the following 2 methods for multiplying 2 integers: let multBland = function (x,y) -> x*y;; let multSpice = function x -> function y -> x* y;; #multBland : int * int -> int = <fun> #multSpice : int -> int -> int = <fun> multBland(3,4) evaluates to 12 multSpice 3 4 evaluates to 12 Note: the different syntax for the different calls! TSP: Software Engineering
#multBland : int * int -> int = <fun> #multSpice : int -> int -> int = <fun> Let’s spice it up! • Let us examine multSpice (multBland is nothing new) • We can informally interpret the type of multSpice as: • multSpice is a function which takes an integer and returns a function which takes an integer and returns an integer • multSpice is a curried function … but what use is it? • We can use it to define new functions (not just to evaluate expressions) • For example, • let triple = multSpice 3;; • triple : int -> int = <fun> TSP: Software Engineering
Higher Order Functions • Caml allows us to pass functions as parameters to other functions. • These other functions are said to be higher-order. • Two classic examples are: • map --- take a function and a list of elements and apply the function to all the list elements, generating a new list • filter --- take a boolean function and a list of elements and, using the function, test each of the elements and generate a new list by keeping only those elements which test true. • For example: • map double [1,2,3,4] = [2,4,6,8] • filter even [1,2,3,4] = [2,4] Question: can you write Caml for map and filter? TSP: Software Engineering
Map and filter let rec map = function fn -> function [] -> [] | a::b -> (fn a) ::(map fn b);; let rec filter = function property -> function [] -> [] | a::b -> if property a then a:: filter property b else filter property b;; Question: can you work out the types of these functions? TSP: Software Engineering
Reduce Complementary to mapis the functionwhichreduces a listinto a single element. For example reduceadd [1;2;4;8] = 15 QUESTION : Whatis the type of reduce? Can youwrite the reducefunction? MapReduce is a programming model for processing large data sets, it is inspired by the map and reduce functions commonly used in functional programming TSP: Software Engineering
A classic problem --- graph algorithms • In Computer Science, graph algorithms are found everywhere • Normally, it takes quite some time before they can be programmed by beginners • With a functional language we can start immediately • So, where do we begin: • data structure • functions • both? Let us try to do it interactively with the Caml! TSP: Software Engineering
The graph algorithm problem Informal Requirements: I have a graph of nodes connected by links and I wish to be able to test if there is a way of getting between any 2 nodes by following the links. Analysis: The main problem is to find a good representation of the graph, then we need only write one boolean function to fulfil the requirements Design: We decide to do it in Caml so we target our design towards a representation which uses only lists and tuples. Question: how many (good) representations can you find? TSP: Software Engineering
Different Types of Graph • Through our initial modelling of graphs we realise that the customer’s requirements are incomplete --- we need additional information as to the type of the graph being considered: • connected or disjoint • unidirectional or bidirectional links • with or without circuits • can one node always get to itself along an empty path? TSP: Software Engineering
One Possibility Best to start with a typical graph and try representing it in Caml: 4 2 3 5 1 7 6 let G = [(1,[2]); (2,[3;5]); (3,[7]); (4,[5]); (5,[7]); (6, [5]); (7,[])];; TSP: Software Engineering
Test the representation The general case shows that we can represent 1 particular graph. We should also test special cases (which may be chosen as problematic to our requirements): • let loop1 = [1, [1]];; • let loop12 = [1, [2]; 2, [1]];; • let midloop = [1, [2]; 2, [1; 3]; 3, []; 4, [1]];; • let Gloops = [1, [2]; 2, [1; 2; 7]; 3, [4]; 4, [5; 6]; 5, [3; 7]; 6, [7; 3]; 7, [7]];; Question: what assumptions do we make about our graphs represented in this way? Do we need an invariant property? TSP: Software Engineering
Some Graph Functions • Before we try to write the ‘find a path’ function, we should make sure we know how to write simple functions on our graph data structure. • Write a function to check if a node is in the graph • Write a function to check if there is an arc from 1 node to another • Write a function to check if a given node is a dead end NOTE: you may need some helper functions like empty, for testing if a list is empty TSP: Software Engineering
TO DO: WriteCaml code to check if thereis a pathbetween 2 nodes in a directed graph, and test it TSP: Software Engineering