Commit 9e7512e5 authored by James R. Wilcox's avatar James R. Wilcox
Browse files

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 = <fun> *)
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