In tro duction to F unctional Programming: Lecture 6 1 In tro duction to F unctional Programming John Harrison Univ ersit y of Cam bridge Lecture 6 E�ectiv e ML T opics co v ered: � Using standard com binators � Abstract t yp es � T ail recursion and accum ulators � F orcing ev aluation � Minimizing consing John Harrison Univ ersit y of Cam bridge, 27 Jan uary 1998
In tro duction to F unctional Programming: Lecture 6 2 Using standard com binators It often turns out that a few c ombinators are v ery useful: w e can implemen t practically an ything b y plugging them together, esp ecially giv en higher order functions. F or example, the itlist function: itlist f [ x ; x ; : : : ; x ] b 1 2 n = f x ( f x ( f x ( � � � ( f x b )))) 1 2 3 n can often b e used to a v oid explicit recursiv e de�nitions o v er lists. W e de�ne it as: - fun itlist f [] b = b | itlist f (h::t) b = f h (itlist f t b); > val itlist = fn : ('a -> ('b -> 'b)) -> 'a list -> 'b -> 'b F unctions of this sort are often built in to functional langauges, and sometimes called something lik e fold . John Harrison Univ ersit y of Cam bridge, 27 Jan uary 1998
In tro duction to F unctional Programming: Lecture 6 3 Itlist examples (1) F or example, here is a function to add up all the elemen ts of a list: - fun sum l = itlist (fn x => fn sum => x + sum) l 0; > val sum = fn : int list -> int - sum [1,2,3,4,5]; > val it = 15 : int - sum []; > val it = 0 : int If w e w an t to m ultiply the elemen ts instead, w e c hange it to: - fun prod l = itlist (fn x => fn prod => x * prod) l 1; > val prod = fn : int list -> int - prod [1,2,3,4,5]; > val it = 120 : int John Harrison Univ ersit y of Cam bridge, 27 Jan uary 1998
In tro duction to F unctional Programming: Lecture 6 4 Itlist examples (2) Here is a �ltering function: - fun filter p l = itlist (fn x => fn s => if p x then x::s else s) l []; and here are some logical op erations o v er lists: - fun forall p l = itlist (fn h => fn a => p(h) andalso a) l true; - fun exists p l = itlist (fn h => fn a => p(h) orelse a) l false; and some old fa v ourites: - fun length l = itlist (fn x => fn s => s + 1) l 1; - fun append l m = itlist (fn h => fn t => h::t) l m; - fun map f l = itlist (fn x => fn s => (f x)::s) l []; John Harrison Univ ersit y of Cam bridge, 27 Jan uary 1998
In tro duction to F unctional Programming: Lecture 6 5 Itlist examples (3) W e can implemen t set op erations quite directly using these com binators as building blo c ks. - fun mem x l = exists (fn y => y = x) l; - fun insert x l = if mem x l then l else x::l; - fun union l1 l2 = itlist insert l1 l2; - fun setify l = union l []; - fun Union l = itlist union l []; - fun intersect l1 l2 = filter (fn x => mem x l2) l1; - fun subtract l1 l2 = filter (fn x => not (mem x l2)) l1; - fun subset l1 l2 = forall (fn t => mem t l2) l1; John Harrison Univ ersit y of Cam bridge, 27 Jan uary 1998
In tro duction to F unctional Programming: Lecture 6 6 Abstract t yp es An abstract t yp e starts with an ordinary recursiv e t yp e, and then imp oses restrictions on ho w the ob jects of the t yp e can b e manipulated. Essen tially , users can only in teract b y a particular `in terface' of functions and v alues. The adv an tage is that users c annot rely on an y other in ternal details of the t yp e. This impro v es mo dularit y , e.g. it is easy to replace the implemen tation of the abstract t yp e with a new `b etter' (smaller, faster, not paten ted . . . ) one, without requiring an y c hanges to user co de. John Harrison Univ ersit y of Cam bridge, 27 Jan uary 1998
In tro duction to F unctional Programming: Lecture 6 7 Example: sets (1) Here is an abstract t yp e for in teger sets. - abstype set = Set of int list with val empty = Set [] fun set_insert a (Set s) = Set (insert a s) fun set_union (Set s) (Set t) = Set (union s t) fun set_intersect (Set s) (Set t) = Set (intersect s t) fun set_subset (Set s) (Set t) = subset s t end; Users can't access the in ternal represen tation (lists), whic h is only done via the in terface functions. John Harrison Univ ersit y of Cam bridge, 27 Jan uary 1998
In tro duction to F unctional Programming: Lecture 6 8 Example: sets (2) Man y of the op erations are m uc h more e�cien t if w e k eep the lists sorted in to n umerical order. F or example: - fun sunion [] [] = [] | sunion [] l = l | sunion l [] = l | sunion (h1::t1) (h2::t2) = if h1 < h2 then h1::(sunion t1 (h2::t2)) else if h1 > h2 then h2::(sunion (h1::t1) t2) else h1::(sunion t1 t2); > val sunion = fn : int list -> int list -> int list W e can c hange the in ternal represen tation to use sorted lists (or balanced trees, or arra ys, . . . ) and no c hanges are needed to co de using the abstract t yp e. John Harrison Univ ersit y of Cam bridge, 27 Jan uary 1998
In tro duction to F unctional Programming: Lecture 6 9 Storing lo cal v ariables Recall our de�nition of the factorial: #fun fact n = if n = 0 then 1 else n * fact(n - 1); A call to fact 6 causes another call to fact 5 (and b ey ond), but the computer needs to sa v e the old v alue 6 in order to do the �nal m ultiplication. Therefore, the lo cal v ariables of a function, in this case n , cannot b e stored in a �xed place, b ecause eac h instance of the function needs its o wn cop y . Instead eac h instance of the function is allo cated a frame on a stack . This tec hnique is similar in ML to most other languages that supp ort recursion, including C. John Harrison Univ ersit y of Cam bridge, 27 Jan uary 1998
In tro duction to F unctional Programming: Lecture 6 10 The stac k Here is an imaginary snapshot of the stac k during the ev aluation of the innermost call of fact : n = 6 n = 5 n = 4 n = 3 n = 2 n = 1 n = 0 - SP Note that w e use ab out n w ords of storage when there are n nested recursiv e calls. In man y situations this is v ery w asteful. John Harrison Univ ersit y of Cam bridge, 27 Jan uary 1998
In tro duction to F unctional Programming: Lecture 6 11 A tail recursiv e v ersion No w, b y con trast, consider the follo wing implemen tation of the factorial function: - fun tfact x n = if n = 0 then x else tfact (x * n) (n - 1); > val tfact = fn : int -> int -> int - fun fact n = tfact 1 n; > val fact = fn : int -> int - fact 6; > val it = 720 : int The recursiv e call is the whole expression; it do es not o ccur as a prop er sub expression of some other expression in v olving v alues of v ariables. Suc h a call is said to b e a tail c al l b ecause it is the v ery last thing the calling function do es. A function where all recursiv e calls are tail calls is said to b e tail r e cursive . John Harrison Univ ersit y of Cam bridge, 27 Jan uary 1998
In tro duction to F unctional Programming: Lecture 6 12 Wh y tail recursion? If a function is tail recursiv e, the compiler is clev er enough to realize that the same area of storage can b e used for the lo cal v ariables of eac h instance. W e a v oid using all that stac k. The additional argumen t x of the tfact function is called an ac cumulator , b ecause it accum ulates the result as the recursiv e calls stac k up, and is then returned at the end. W orking in this w a y , rather than mo difying the return v alue on the w a y bac k up, is a common w a y of making functions tail recursiv e. In a sense, a tail recursiv e implemen tation using accum ulators corresp onds to an iterativ e v ersion using assignmen ts and while-lo ops. The only di�erence is that w e pass the state around explicitly . John Harrison Univ ersit y of Cam bridge, 27 Jan uary 1998
Recommend
More recommend