Download presentation

Presentation is loading. Please wait.

Published byMara Brattle Modified over 2 years ago

1
Higher-order functions in OCaml

2
Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function has one or more first-order functions as parameters or result In general, a higher-order function has one or more functions as parameters or result OCaml supports higher-order functions

3
Doubling, revisited # let rec doubleAll = function [] -> [] | (h::t) -> (2 * h)::(doubleAll t);; val doubleAll : int list -> int list # doubleAll [1;2;3;4;5];; - : int list = [2; 4; 6; 8; 10] This is the usual heavy use of recursion It's time to simplify things

4
map map applies a function to every element of a list and returns a list of the results map f [x, y, z] returns [f x, f y, f z] Notice that map takes a function as an argument Ignore for now the fact that map appears to take two arguments!

5
Doubling list elements with map # let double x = 2 * x;; val double : int -> int = # let doubleAll lst = map double lst;; val doubleAll : int list -> int list = # doubleAll [1;2;3;4;5];; - : int list = [2; 4; 6; 8; 10] The definition of doubleAll is simpler, but......now we need to expose double to the world

6
Anonymous functions An anonymous function has the form (fun parameter -> body ) Now we can define doubleAll as let doubleAll lst = map (fun x -> 2*x) lst;; This final definition is simple and doesn't require exposing an auxiliary function

7
The mysterious map ML functions all take a single argument, but... map double [1;2;3] works map (double, [1;2;3]) gives a type error Even stranger, (map double) [1;2;3] works! # map double;; - : int list -> int list = map double looks like a function...how?

8
Currying In OCaml, functions are values, and there are operations on those values Currying absorbs a parameter into a function, creating a new function map takes one argument (a function), and returns one result (also a function)

9
Order of operations let add (x, y) = x + y;; –# val add : int * int -> int = But also consider: # let add x y = x + y;; –val add : int -> int -> int = add x y is grouped as (add x) y and int -> int -> int as int -> (int -> int)

10
Writing a curried function I # let add x y = x + y;; –val add : int -> int -> int = –That is, add has type int -> (int -> int) –Our new add takes an int argument and produces an (int -> int) result (add 5) 3;; (* currying happens *) - : int = 8

11
Writing a curried function II let addFive = add 5;; –# val addFive : int -> int = –Notice this is a val; we are manipulating values # addFive 3;; (* use our new function *) –- : int = 8

12
Defining higher-order functions I # let apply1 (f, x) = f x;; val apply1 : ('a -> 'b) * 'a -> 'b = # apply1 (tl, [1;2;3]);; - : int list = [2; 3] But: # apply1 tl [1;2;3];; –Characters 7-9: This expression has type 'a list -> 'a list but is here used with type ('b -> int list -> 'c) * 'b

13
Defining higher-order functions II # let apply2 f x = f x;; val apply2 : ('a -> 'b) -> 'a -> 'b = # apply2 tl [1;2;3];; - : int list = [2; 3] # apply2 (tl, [1;2;3]);; Characters 8-19: This expression has type ('a list -> 'a list) * int list but is here used with type 'b -> 'c Advantage: this form can be curried

14
A useful function: span span finds elements at the front of a list that satisfy a given predicate Example: span even [2;4;6;7;8;9;10] gives [2, 4; 6] span isn't a built-in; we have to write it

15
Implementing span # let rec span f lst = if f (hd lst) then (hd lst)::span f (tl lst) else [];; val span : ('a -> bool) -> 'a list -> 'a list = # span even [2;4;6;7;8;9;10];; - : int list = [2; 4; 6]

16
Extending span: span2 span returns the elements at the front of a list that satisfy a predicate Suppose we extend it to also return the remaining elements We can do it with the tools we have, but more tools would be convenient

17
Generalized assignment # let (a, b, c) = (8, 3, 6);; –val a : int = 8 val b : int = 3 val c : int = 6 # let (x::xs) = [1;2;3;4];; –(* Non-exhaustive match warning deleted *) val x : int = 1 val xs : int list = [2; 3; 4] Generalized assignment is especially useful when a function returns a tuple

18
Defining local values with let let declaration in expression let decl1 in let decl2 in expression # let a = 5 in let b = 10 in a + b;; - : int = 15 let helps avoid redundant computations

19
Example of let # let circleArea radius = let pi = 3.1416 in let square x = x *. x in pi *. square radius;; val circleArea : float -> float = # circleArea 10.0;; - : float = 314.160000

20
Implementing span2 # let rec span2 f lst = if f (hd lst) then let (first, second) = span2 f (tl lst) in ((hd lst :: first), second) else ([], lst);; val span2 : ('a -> bool) -> 'a list -> 'a list * 'a list = # span2 even [2;4;6;7;8;9;10];; - : int list * int list = [2; 4; 6], [7; 8; 9; 10]

21
Another built-in function: partition Partition breaks a list into two lists: those elements that satisfy the predicate, and those that don't Example: # partition even [2;4;6;7;8;9;10];; - : int list * int list = [2; 4; 6; 8; 10], [7; 9]

22
Quicksort Choose the first element as a pivot: –For [3;1;4;1;5;9;2;6;5] choose 3 as the pivot Break the list into elements pivot: –[1; 1; 2] and [4; 5; 9; 6; 5] Quicksort the sublists: –[1; 1; 2] and [4; 5; 5; 6; 9] Append the sublists with the pivot in the middle: –[1; 1; 2; 3 ; 4; 5; 5; 6;, 9]

23
Quicksort in ML let rec quicksort = function [] -> [] | (x::xs) -> let (front, back) = partition (fun n -> n <= x) xs in (quicksort front) @ (x::(quicksort back));; val quicksort : 'a list -> 'a list = # quicksort [3;1;4;1;5;9;2;6;5;3;6];; - : int list = [1; 1; 2; 3; 3; 4; 5; 5; 6; 6; 9]

24
Testing if a list is sorted The following code tests if a list is sorted: # let rec sorted = function [] -> true | [_] -> true | (x::y::rest) -> x <= y && sorted (y::rest);; –val sorted : 'a list -> bool = This applies a (boolean) test to each adjacent pair of elements and "ANDs" the results Can we generalize this function?

25
Generalizing the sorted predicate let rec sorted list = match list with [] -> true | [_] -> true | (x::y::rest) -> x <= y && sorted (y::rest);; The underlined part is the only part specific to this particular function We can replace it with a predicate passed in as a parameter

26
pairwise let rec pairwise f list = match list with [] -> true | [_] -> true | (x::y::rest) -> (f x y) && pairwise f (y::rest);; Here are the changes we have made: –Changed the name from sorted to pairwise –Added the parameter f in two places –changed x <= y to (f x y)

27
Using pairwise # pairwise (<=) [1;3;5;5;9];; - : bool = true # pairwise (<=) [1;3;5;9;5];; - : bool = false # pairwise (fun x y -> x = y - 1) [3;4;5;6;7];; - : bool = true # pairwise (fun x y -> x = y - 1) [3;4;5;7];; - : bool = false

28
The End

Similar presentations

OK

Patterns in OCaml functions. Formal vs. actual parameters Here's a function definition (in C): –int add (int x, int y) { return x + y; } –x and y are.

Patterns in OCaml functions. Formal vs. actual parameters Here's a function definition (in C): –int add (int x, int y) { return x + y; } –x and y are.

© 2017 SlidePlayer.com Inc.

All rights reserved.

Ads by Google

Ppt on applied operational research Ppt on chapter 3 atoms and molecules youtube Ppt on earthquake resistant design of structures Ppt on different occupations in india Ppt on bond length table Ppt on pre ignition detonation Ppt on kingdom monera definition Ppt on earth dam Best ppt on water cycle Ppt on vertical axis wind turbine