Download presentation
Presentation is loading. Please wait.
Published byJocelyn Cox Modified over 10 years ago
1
Tutorial 5
2
Recap For a function f which takes arguments arg1, arg2,... argn, and returns type rettype, the compiler will print: f : arg1 -> arg2 ->... -> argn -> rettype _____________ Element::list If the list is of type ’a list then the element needs to be of type ’a The empty list is polymorphic: it can be used with elements of any type. __________ list @ list The two lists need to be of the same type!
3
= VS == = (structural equality ) – e1 = e2 tests for structural equality of e1 and e2. Mutable structures are equal if and only if their current contents are structurally equal, even if the two mutable objects are not the same physical object. == (Physical equality ) – e1 == e2 tests for physical equality of e1 and e2.
4
= VS == # let x=[1;2];; val x : int list = [1; 2] # let y=[1;2];; val y : int list = [1; 2] # let z=x;; val z : int list = [1; 2] # y=x;; - : bool = true # z=x;; - : bool = true # y==x;; - : bool = false # z==x;; - : bool = true
5
Binding Issues let foo x = x+5;; val foo : int -> int = let bar = foo;; val bar : int -> int = let foo x = x+6;; val foo : int -> int = Results of foo 1;; ? - : int = 7 Results of bar 1;; ? - : int = 6
6
Find the error let rec foo ls= match ls with []->[] |x::xs-> foo x::xs Error: This expression has type 'a but an expression was expected of type 'a list The type variable 'a occurs inside 'a list Error: This expression has type 'a but an expression was expected of type 'a list The type variable 'a occurs inside 'a list
7
Find the bug let rec foo ls= match ls with []->[] |x::xs-> foo (x::xs) Error fixed but the code now contains a Logical bug: infinite recursion recurring on the list without making it smaller every time you call the function again which means you will never reach the base case ([]->..) where you stop the recursion Error fixed but the code now contains a Logical bug: infinite recursion recurring on the list without making it smaller every time you call the function again which means you will never reach the base case ([]->..) where you stop the recursion
8
Find the error let rec foo = function _,[]->[] |n,x::xs-> foo (n-1) xs; Error: This function has type int * 'a list -> 'b list It is applied to too many arguments; maybe you forgot a `;'. Error: This function has type int * 'a list -> 'b list It is applied to too many arguments; maybe you forgot a `;'.
9
Find the error let rec foo = function _,[]->[] |n,x::xs-> foo ((n-1),xs);; val foo : int * 'a list -> 'b list = If you want the type of foo to be val foo : int -> 'a list -> 'b list = Then do this: – let rec foo n ls = match n,ls with _,[]->[] |n,x::xs-> foo (n-1) xs;;
10
E1 Consider the Llama game. For the purpose of this problem a final (winning) position in the game is when all right-facing llamas are past all the left facing llamas. You are given the type of llamas: type llama = R | L | O Your task is to write a function winning : llama list -> bool which returns true if a position is winning and false otherwise. For example: winning [R; O; L] = false winning [O; O; L; L; R; O; R; O] = true
11
E1 solution open Common;; let rec drop_lefts = function | O::state -> drop_lefts state | L::state -> drop_lefts state | state -> state;; let rec only_rights = function | L::_ -> false | _::state -> only_rights state | _ -> true;; let winning state = only_rights (drop_lefts state);;
12
E2 Consider the llama game Your task is to write a function is_move : llama list -> llama list -> bool which returns true if it is possible to go from the first position to the second position in a single move and false otherwise. For example: is_move [R; O; L] [O; R; L] = true is_move [R; O; L] [R; L] = true is_move [R; O; L] [L; R] = false
13
Functions used from Module List http://caml.inria.fr/pub/docs/manual-ocaml/libref/List.htmlList val map : ('a -> 'b) -> 'a list -> 'b list – List.map f [a1;...; an] applies function f to a1,..., an, and builds the list [f a1;...; f an] with the results returned by f. val mem : 'a -> 'a list -> bool – mem a l is true if and only if a is equal to an element of l. val filter : ('a -> bool) -> 'a list -> 'a list – filter p l returns all the elements of the list l that satisfy the predicate p. The order of the elements in the input list is preserved.
14
solution open Common;; open List;; let rec add_pref x = map (fun xs -> x :: xs);; val add_pref : 'a -> 'a list list -> 'a list list = let rec get_next = function | R :: O :: xs -> (O :: R :: xs) :: (add_pref R (get_next (O :: xs))) | O :: L :: xs -> (L :: O :: xs) :: (add_pref O (get_next (L :: xs))) | R :: L :: O :: xs -> (O :: L :: R :: xs) :: (add_pref R (get_next (L :: O :: xs))) | O :: R :: L :: xs -> (L :: R :: O :: xs) :: (add_pref O (get_next (R :: L :: xs))) | x :: xs -> add_pref x (get_next xs) | [] -> [];; val get_next : llama list -> llama list list =
15
solution let rec expand pos vstd = let pos_list = get_next pos in filter (fun pos -> not (mem pos vstd)) pos_list val expand : llama list -> llama list list -> llama list list = let rec strip_los = function | O :: xs -> strip_los xs | xs -> xs val strip_los : llama list -> llama list = let strip_os xs = xs |> strip_los |> rev |> strip_los |> rev;; val strip_os : llama list -> llama list = let is_move xs ys = let xss = expand ([O] @ xs @ [O]) [] |> map strip_os in mem (strip_os ys) xss val is_move : llama list -> llama list -> bool =
16
Tracing get_next get_next [O;R;O;L;O];; 1.add_pref O (get_next [R;O;L;O]) 2.[O;R;L;O]::(add_pref R (get_next [O;L;O])) 3.[L;O;O]::(add_pref O (get_next [L;O])) 4.add_pref L (get_next [O]) 5.add_pref O (get_next []) 6.[] | x :: xs -> add_pref x (get_next xs) | R :: O :: xs -> (O :: R :: xs) :: (add_pref R (get_next (O :: xs))) | O :: L :: xs -> (L :: O :: xs) :: (add_pref O (get_next (L :: xs))) | x :: xs -> add_pref x (get_next xs) | [] -> [];; Pattern matched:
17
Tracing get_next get_next [O;R;O;L;O];; 1.add_pref O (get_next [R;O;L;O]) 2.[O;R;L;O]::(add_pref R (get_next [O;L;O])) 3.[L;O;O]::(add_pref O (get_next [L;O])) 4.add_pref L (get_next [O]) 5.add_pref O (get_next []) 6.[]
18
Tracing get_next get_next [O;R;O;L;O];; 1.add_pref O (get_next [R;O;L;O]) 2.[O;R;L;O]::(add_pref R (get_next [O;L;O])) 3.[L;O;O]::(add_pref O (get_next [L;O])) 4.add_pref L (get_next [O]) 5.add_pref O ([])
19
Tracing get_next get_next [O;R;O;L;O];; 1.add_pref O (get_next [R;O;L;O]) 2.[O;R;L;O]::(add_pref R (get_next [O;L;O])) 3.[L;O;O]::(add_pref O (get_next [L;O])) 4.add_pref L ([])
20
Tracing get_next get_next [O;R;O;L;O];; 1.add_pref O (get_next [R;O;L;O]) 2.[O;R;L;O]::(add_pref R (get_next [O;L;O])) 3.[L;O;O]::(add_pref O (get_next [L;O])) 4.add_pref L ([])
21
Tracing get_next get_next [O;R;O;L;O];; 1.add_pref O (get_next [R;O;L;O]) 2.[O;R;L;O]::(add_pref R (get_next [O;L;O])) 3.[L;O;O]::(add_pref O [])
22
Tracing get_next get_next [O;R;O;L;O];; 1.add_pref O (get_next [R;O;L;O]) 2.[O;R;L;O]::(add_pref R (get_next [O;L;O])) 3.[L;O;O]::([])
23
Tracing get_next get_next [O;R;O;L;O];; 1.add_pref O (get_next [R;O;L;O]) 2.[O;R;L;O]::(add_pref R (get_next [O;L;O])) 3.[[L;O;O]]
24
Tracing get_next get_next [O;R;O;L;O];; 1.add_pref O (get_next [R;O;L;O]) 2.[O;R;L;O]::(add_pref R [[L;O;O]] )
25
Tracing get_next get_next [O;R;O;L;O];; 1.add_pref O (get_next [R;O;L;O]) 2.[O;R;L;O]::( [[R;L;O;O]] )
26
Tracing get_next get_next [O;R;O;L;O];; 1.add_pref O ([[O;R;L;O]; [R;L;O;O]] )
27
Tracing get_next get_next [O;R;O;L;O];; = [[O; O; R; L; O]; [O; R; L; O; O]]
28
Problem Your task is to write a function has_solution : llama list -> bool which returns true if and only if there is some sequence of valid moves from the given position to any winning position. For example has_solution [R; R; O; L; L] = true has_solution [R; R; L; L] = false
29
Functions used from Module ListList val rev_append : 'a list -> 'a list -> 'a list – List.rev_append l1 l2 reverses l1 and concatenates it to l2. This is equivalent to List.rev l1 @ l2, but rev_append is tail-recursive and more efficient.List.rev val sort : ('a -> 'a -> int) -> 'a list -> 'a list – Sort a list in increasing order according to a comparison function. – The comparison function must return 0 if its arguments compare as equal, a positive integer if the first is greater, and a negative integer if the first is smaller
30
solution let rec has_path (src: llama list list) vstd = match src with | [] -> false | x :: xs -> winning x || let src' = expand x vstd in let src = combine xs src' in has_path src (x :: vstd) ;; let has_solution src = has_path [[O] @ src @ [O]] [];;
31
solution let rec strip_ls = function | O :: xs -> strip_ls xs | L :: xs -> strip_ls xs | xs -> xs;; let rec strip_rs = function | O :: xs -> strip_rs xs | R :: xs -> strip_rs xs | xs -> xs;; let rec winning pos = pos |> strip_ls |> rev |> strip_rs = [];;
32
solution let rec add_pref x = map (fun xs -> x :: xs);; let rec get_next = function | R :: O :: xs -> (O :: R :: xs) :: (add_pref R (get_next (O :: xs))) | O :: L :: xs -> (L :: O :: xs) :: (add_pref O (get_next (L :: xs))) | R :: L :: O :: xs -> (O :: L :: R :: xs) :: (add_pref R (get_next (L :: O :: xs))) | O :: R :: L :: xs -> (L :: R :: O :: xs) :: (add_pref O (get_next (R :: L :: xs))) | x :: xs -> add_pref x (get_next xs) | [] -> [];; let rec expand pos vstd = let pos_list = get_next pos in filter (fun pos -> not (mem pos vstd)) pos_list;
33
solution let rec elim_consec = function | [] -> [] | [x] -> [x] | x :: x' :: xs -> if x = x' then elim_consec (x' :: xs) else x :: elim_consec (x' :: xs);; let rec elim_dupls xs = xs |> sort compare |> elim_consec ;; let combine xs ys = elim_dupls (rev_append xs ys);;
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.