1/120
Looks like no tags are added yet.
(HW04) implement ‘assoc’ without using ‘failwith’; more true to its type
let rec assoc (k: 'k) (l: ('k * 'v) list) : 'v option =
begin match l with
| [] -> None
| (key, v)::tl -> if k = key then Some v else assoc k tl
end(HW04) converts optional optional value to just optional value
let join_option (x: 'a option option) : 'a option =
begin match x with
| None -> None
| Some(None) -> None
| Some(Some v) -> (Some v)
end(HW04) takes in list of optional values and returns list containing all values present.
let rec cat_option (l: 'a option list) : 'a list =
begin match l with
| [] -> []
| None::tail -> cat_option tail
| (Some v)::tail -> v::(cat_option tail)
end(HW04) transforms a list with function f and returns list containing all values “present” after transportation
let rec partial_transform (f: 'a -> 'b option) (l: 'a list) : 'b list =
begin match l with
| [] -> []
| v::tail ->
begin match f v with
| None -> partial_transform f tail
| Some x -> x::(partial_transform f tail)
end(HW04) iterates through each element of a list in order and calls side-effecting function on each element.
let rec iter (f: 'a -> unit) (l: 'a list) : unit =
begin match l with
| [] -> ()
| x::tail -> f x ; iter f tail
end(HW04) determines of two record cells are aliased by using reference equality operator.
let states_aliased (r1: state) (r2: state) : bool =
r1 == r2(HW04) swaps contents of two state record cells
let swap (r1: state) (r2: state) : unit =
let a = r1.count in
let b = r2.count in
r2.count <- a ; r1.count <- b(HW04) given value x and list of values, determine whether any of the elements in the list is an alias of x.
let rec contains_alias (x: 'a) (l: 'a list) : bool =
begin match l with
| [] -> false
| hd::tail -> x == hd || contains_alias x tail
end(HW04) determines whether given value x is aliased with one of the avlues inside an option in an options list.
let rec contains_alias_option (x: 'a) (l: 'a option list) : bool =
begin match l with
| [] -> false
| None::tl -> contains_alias_option x tl
| Some hd::tl -> x == hd || contains_alias_option x tl
end(HW04) all simpleQueues are valid
let valid (q: 'a queue) : bool =
true(HW04) create empty SimpleQueue
let create () : 'a queue =
{ data = [] }(HW04) determine whether queue is empty
let is_empty (q: 'a queue) : bool =
q.data = [](HW04) SimpleQueue: delete all instances of the value elt from the queue
let delete (elt: 'a) (q: 'a queue) : unit =
q.data <- fold (fun v acc -> if v = elt then acc else v :: acc) [] q.data(HW04) LinkedQueue: queue invariant
q.head and q.tail are either both None, or
q.head and q.tail both point to Some nodes, and
q.tail is reachable by following 'next' pointers from q.head
q.tail's next pointer is None (This implies a valid queue has no cycles.)
(HW04) LinkedQueue: add an element to the tail of a queue
let enq (elt: 'a) (q: 'a queue) : unit =
if not (valid q) then failwith "enq: given invalid queue";
let newnode = Some { v = elt; next = None } in
begin match q.tail with
| None ->
(* Note that the invariant tells us that q.head is also None *)
q.head <- newnode;
q.tail <- newnode
| Some n ->
n.next <- newnode;
q.tail <- newnode
end(HW04) LinkedQueue: remove an element from the head of the queue
let deq (q: 'a queue) : 'a option =
if not (valid q) then failwith "deq: given invalid queue";
begin match q.head with
| None ->
None
| Some n ->
q.head <- n.next;
begin match n.next with
| None -> q.tail <- None; Some n.v
| Some _ -> Some n.v
end
end(HW04) LinkedQueue: delete all nodes containing elt in place (structural equality)
let delete (elt: 'a) (q: 'a queue) : unit =
if not (valid q) then failwith "delete: given invalid queue";
let rec loop (prev: 'a qnode option) (curr: 'a qnode option) : unit =
begin match curr with
| None -> q.tail <- prev
| Some n ->
if n.v = elt then
begin (match prev with
| None -> q.head <- n.next
| Some n1 -> n1.next <- n.next);
loop prev n.next
end
else loop curr n.next
end
in loop None q.head