### L19 code

parent 43f079a5
 (* currying recap *) let rec filter f = (fun xs -> match xs with | [] -> [] | x :: xs' -> if f x then x :: ((filter f) xs') else ((filter f) xs')) let is_even x = x mod 2 = 0 let only_evens xs = filter is_even xs let only_evens = filter is_even let rec filter_old_way (f, xs) = match xs with | [] -> [] | x :: xs' -> if f x then x :: filter_old_way (f, xs') else filter_old_way (f, xs') let convert_from_tupled_to_curried g = fun x -> fun y -> g (x, y) (* val convert_from_tupled_to_curried : ('a * 'b -> 'c) -> 'a -> 'b -> 'c = *) let filter_converted f = convert_from_tupled_to_curried filter_old_way f let curry g x y = g (x, y) let uncurry g (x, y) = g x y let filter_unconverted_for_no_reason f = uncurry filter_converted f (* Functional programming - expression-oriented - variant types and pattern matching - first-class functions ("functions are values") - tour of closure idioms - take a function as an argument - return a function as a result - a closure "captures" data from its defining environment to use later - currying (and uncurrying) TODAY: - "combining functions" - "let over lambda" - refs and mutation *) (* function composition: takes two functions and returns a function *) let compose = fun f -> fun g -> fun x -> f (g x) let compose f g = fun x -> f (g x) let compose f g x = f (g x) let add_one n = n + 1 let double n = 2 * n let add_one_then_double = compose double add_one let double_then_add_one = compose add_one double (* proof that function composition is not commutative *) let (|>) x f = f x let n = 10 |> add_one |> double let n = 10 |> add_one |> double let m = 10 |> double |> add_one (* compose_option *) (* if f has this type: f : 'a -> 'b option can think of f as a function from 'a to 'b that can fail If we have two such functions, what is the correct way to compose them? g : 'b -> 'c option The "composition" of f and g, which should be a function of this type 'a -> 'c option If either step fails, the whole thing fails. If both succeed, then we return the result of g *) let compose_option (g: 'b -> 'c option) (f: 'a -> 'b option): 'a -> 'c option = fun (x : 'a) -> match f x with | None -> None | Some (y : 'b) -> g y let ten_divided_by n = if n = 0 then None else Some (10 / n) let safe_hd l = match l with | [] -> None | x :: _ -> Some x let foo = compose_option ten_divided_by safe_hd (* refs and mutation *) let x = 10 let r = ref 10 (* r has type "int ref" *) (* the type "t ref" - a mutable reference to a value of type t - provides operations for reading and writing the reference t ref IS NOT COMPATIBLE with type t - build values of type "t ref" - use "ref e" where e is any expression - evaluate e to value v, and then create a new reference whose initial contents is v - use values of type "t ref" - read the value of the reference using "!e" where e is any expression - evaluates to a value v - OCaml's type system guarantees that v is a reference - the result is the current contents of the reference - write a value using "e1 := e2" - evaluate e1 to value v1 - evaluate e2 to value v2 - OCaml's type system guarantees that v1 is a reference - change the contents of the reference v1 to v2 *) (* to read the ref, use "!" operator *) let y = !r let _ = r := 11 let z = !r (* let w = 1 + r (* error! r is not an int *) *) let w = 1 + !r (* let _ = x := 17 (* error! x is not an int ref *) *) let _ = r := 17 let r2: int option ref = ref None (* ... many lines later ... *) let _ = r2 := Some 5 (* let over lambda *) (* idea: implement something like an ADT or an object *) (* example: map from keys to values (keys are ints and values are strings ) internal reprentation: { map: (int * string) list; key_list: int list } internal invariant: key_list = firsts map *) type internal_rep = { map: (int * string) list; key_list: int list } (* imagine there is only one key-value store ADT in the world *) (* "public" *) let setup_library () = let the_map = ref { map = []; key_list = [] } in let insert k v = let m = !the_map in the_map := { map = (k,v) :: m.map; key_list = k :: m.key_list } in let get_contents () = (!the_map).map in (insert, get_contents) let (insert, get_contents) = setup_library ()
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment