I cannot figure out which case I am missing here,for my functions,can someone help me find which case to consider also so that I do not get the match non-exhaustive error.It is taking time for me to really figure out which part is missing.
fun eval_1 (nil,_) = nil
| eval_1 (_,nil) = nil
|eval_1 ((x::h::xs),(y::t::ys)) = if x = ~1 then (h,t)::eval_1(xs,ys) else(x,y)::eval_1(h::xs,t::ys);
fun eval_2 (nil,_) = nil
| eval_2 (x,nil) = nil
|eval_2 ((x),(y::ys)) = eval_1 (x,y)::eval_2(x,ys);
fun eval_3 (nil,_) = nil
| eval_3 ((x::nil),nil) = nil
| eval_3 ((x::xs),(ys)) = eval_2(x,ys)::eval_3(xs,ys);
Matching on (x:xs, y:ys) instead of ((x::h::xs),(y::t::ys)) gets rid of the non-exhaustive warning. To make the rest of the code equivalent you can use hd and tl from List to get the head of the tail and the tail of the tail instead of decomposing the list with x::next::xs.
fun eval_1 (nil,_) = nil
| eval_1 (_,nil) = nil
| eval_1 (x::xs, y::ys) = if x = ~1 then (hd xs, hd ys)::eval_1(tl xs, tl ys) else (x,y) :: eval_1(xs, ys)
fun eval_2 (nil,_) = nil
| eval_2 (x,nil) = nil
| eval_2 ((x),(y::ys)) = eval_1 (x,y)::eval_2(x,ys);
fun eval_3 (nil,_) = nil
| eval_3 ((x::nil),nil) = nil
| eval_3 ((x::xs),(ys)) = eval_2(x,ys)::eval_3(xs,ys);
Sample run:
> val eval_1 = fn : int list * 'a list -> (int * 'a) list
val eval_2 = fn : int list * 'a list list -> (int * 'a) list list
val eval_3 = fn : int list list * 'a list list -> (int * 'a) list list list
val it = () : unit
> eval_1([1,2,3], [4,5,6]);
val it = [(1, 4), (2, 5), (3, 6)] : (int * int) list
Related
I have a list of (string * int) list elements and I need to find the biggest int element and return the corresponding(string * int) element.
I have something like this atm, but problem is, I think my approach is more of "typical programming"
let it = [] in
for x = 0 to length LIST - 1 do
let str = ((List.nth LIST x).string) in
let num = ((List.nth LIST x).int) in
let it = it # [num, str] in
let (str, num) = List.hd(List.rev it) in
[str, num]
What I tried to do is to loop through the list and add the string and int value in another list, then sort them, reverse it and then take the head, which should be the max int, then I need to return the pair in (string * int)
Your code is not a well-formed OCaml code. It highlights, however, some number of issues with your understanding of OCaml.
First of all, by default, values in OCaml are immutable. For example,
let x = 0 in
for i = 0 to 10 do
let x = x + 1 in
print_int x;
done
You will get 11111111111 as the output. This is because, during the loop, you are just computing every time the x+1 expression, where x is always 0 and you will always get 1 as the result. This is because, let x = <expr> in <body> is not changing the existing variable x but is creating a new variable x (shadowing any previous definitions) and make it available in the scope of the <body> expression.
Concerning your problem in general, it should be solved as a recursive function greatest_element, which has the following definition,
for an empty list [] it is undefined;
for a list of one element [x] is it is x;
otherwise, for a list of x::xs it is max x (greatest_element xs),
where max x y is x if it is greater or equal to y.
Finally, it looks like you have missed the first steps in OCaml and before solving this task you have to move back and to learn the basics. In particular, you have to learn how to call functions, bind variables, and in general what are the lexical conventions and syntax of the language. If you need pointers, feel free to ask.
First of all, it doesn't seem that you did any kind of sorting in
the code that you provided.
Assuming that your list is of type
(string * int) list then a possible to find the element with the
maximum integer using recursion:
let max_in_list list =
let rec auxiliary max_str max_int = function
| []
-> (max_str, max_int)
| (crt_str, crt_int)::tail when crt_int > max_int
-> auxiliary crt_str crt_int tail
| _::tail
-> auxiliary max_str max_int tail
in
match list with
| []
-> None
| (fst_str, fst_int)::tail
-> Some (auxiliary fst_str fst_int tail)
let check = max_in_list [("some", 1); ("string", 3); ("values", 2)]
You could write a generic maxBy function. This allows you to get the max of any list -
let rec maxBy f = function
| [] -> None
| [ x ] -> Some x
| x :: xs ->
match (maxBy f xs) with
| Some y when (f y) > (f x) -> Some y
| _ -> Some x
(* val maxBy : ('a -> 'b) -> 'a list -> 'a option = <fun> *)
let data = [("a", 3); ("b", 2); ("c", 6); ("d", 1)]
(* val data : (string * int) list = [("a", 3); ("b", 2); ("c", 6); ("d", 1)]*)
maxBy (fun (_, num) -> num) data
(* - : (string * int) option = Some ("c", 6) *)
maxBy (fun (str, _) -> str) data
(* - : (string * int) option = Some ("d", 1) *)
maxBy (fun x -> x) [3; 2; 6; 1]
(* - : int option = Some 6 *)
maxBy (fun x -> x) ["c"; "d"; "b"; "a"]
(* - : string option = Some "d" *)
maxBy (fun x -> x) []
(* - : 'a option = None *)
It can be fun to rewrite the same function in various ways. Here's another encoding -
let maxBy f list =
let rec loop r = function
| [] -> r
| x::xs when (f x) > (f r) -> loop x xs
| _::xs -> loop r xs
in
match list with
| [] -> None
| x::xs -> Some (loop x xs)
(* val maxBy : ('a -> 'b) -> 'a list -> 'a option = <fun> *)
How would I go about traversing a list in SMLNJ. I have been at this for 3 hours now and I cannot figure it out for the life of me.
So just to traverse and print a list out. In the simplest way [5,2,3] would print out 5 2 3 or a list variant of this.
How would I go about traversing a list in SMLNJ
It depends on the type of traversal you want to do: mapping, folding, iterating.
Using recursion:
(* mapping: *)
fun incr_each_by_1 [] = []
| incr_each_by_1 (x::xs) = x + 1 :: incr_each_by_1 xs
val demo_1 = incr_each_by_1 [5,2,3] (* [6,3,4] *)
(* folding: *)
fun sum_all_together [] = 0
| sum_all_together (x::xs) = x + sum_all_together xs
val demo_2 = sum [5,2,3] (* 10 *)
(* iteration: *)
fun print_each [] = ()
| print_each (x::xs) = ( print (Int.toString x ^ "\n") ; print_each xs )
val demo_3 = print_each [5,2,3] (* no result, but side-effect *)
Using higher-order functions:
val demo_1 = List.map (fn x => x + 1) [5,2,3]
val demo_2 = List.foldl (fn (x, result) => x + result) 0 [5,2,3]
val demo_3 = List.app (fn x => Int.toString x ^ "\n") [5,2,3]
I've been asked to write a Standard ML Program which deletes every occurrence of a list from another list. For the life of me I cannot understand what is wrong with my code. Any help would be appreciated!
My input for this program is as follows:
deleteAll [1,2,3] [3,2,1,2,3,2,1,2,3];
However my output is this:
val it = [3,2,2,1,2,3] : int list
When it should be: [3,2,2];
fun length(x) = if x = [] then 0 else 1+length(tl(x));
val length = fn : ''a list -> int
fun drop 0 L = L
| drop n [] = raise c4
| drop n (h::t) = drop (n-1) t;
val drop = fn : int -> 'a list -> 'a list
fun starts [] _ = true
| starts _ [] = false
| starts (h::t) (x::xs) = if(h=x) then starts t xs else false;
val starts = fn : ''a list -> ''a list -> bool
fun deleteAll [] _ = []
| deleteAll xs [] = xs
| deleteAll (x::xs) (y::ys) = if(starts (x::xs) (y::ys))
then deleteAll (x::xs) (drop (length(x::xs)) (y::ys))
else y::(deleteAll (x::xs) ys);
val deleteAll = fn : ''a list -> ''a list -> ''a list
First you don't need to create a length function as length is a build-in function that returns an int representing the elements of an 'a list.
One more thing, you raise an exception c4 in your function drop. Then you should also include that in the beginning of your program.
The primary reason your code doesn't work is your deleteAll function base cases. The corrected version should be:
fun deleteAll [] xs = xs (* when the first list is empty, it should return the original list *)
| deleteAll xs [] = [] (* when the second list is empty, it should return an empty list *)
| deleteAll (x::xs) (y::ys) = if(starts (x::xs) (y::ys))
then deleteAll (x::xs) (drop (length(x::xs)) (y::ys))
else y::(deleteAll (x::xs) ys);
The rest is good! After the change the answer should be correct : )
- deleteAll [1,2,3] [3,2,1,2,3,2,1,2,3];
val it = [3,2,2] : int list
I am new to programming in functional languages. I am attempting to implement the F# collect for list.
let rec collect func list =
match list with
| [] -> []
| hd::tl -> let tlResult = collect func tl
func hd::tlResult;;
collect (fun x -> [for i in 1..3 -> x * i]) [1;2;3];;
should print:
val it : int list = [1; 2; 3; 2; 4; 6; 3; 6; 9]
but I got:
val it : int list = [[1; 2; 3;], [2; 4; 6;], [3; 6; 9]]
Here's a tail recursive collect that won't stack overflow for large lists.
let collect f xs =
let rec prepend res xs = function
| [] -> loop res xs
| y::ys -> prepend (y::res) xs ys
and loop res = function
| [] -> List.rev res
| x::xs -> prepend res xs (f x)
loop [] xs
A simpler version, that's somewhat cheating, is:
let collect (f: _ -> list<_>) (xs: list<_>) = [ for x in xs do yield! f x ]
The collect function is tricky to implement efficiently in the functional style, but you can quite easily implement it using the # operator that concatenates lists:
let rec collect f input =
match input with
| [] -> []
| x::xs -> (f x) # (collect f xs)
I am not really understand about the function (parse_list) at
None -> List.rev is and None -> []
let try_parse parse x = try Some (parse x) with Error _ -> None;;
let parse_list parse =
let rec aux is = function
| [] -> List.rev is, []
| (hd :: tl) as xs ->
match try_parse parse hd with
| Some i -> aux (i::is) tl
| None -> List.rev is, xs
in aux [];;
and
let parse_list parse =
let rec aux is = function
| [] -> List.rev is, []
| (hd :: tl) as xs ->
match try_parse parse hd with
| Some i -> aux (i::is) tl
| None -> [], xs
in aux [];;
Are they different? could you please give me an example if they are different? Thank you very much
Yes, they are different.
In the first one, when the parse function will fail, the function parse_list will return a partial list of "parsed" expression (List.rev is).
In the second one, when the parse function will fail, you'll get an empty list from parse_list ([]).
Look this example with a parse function which will keep only integers lesser than 3:
let test_parse x = if x < 3 then x else raise Error "error";;
With the first implementation you'll get:
# parse_list test_parse [1; 2; 3; 4; 5];;
- : int list * int list = ([1; 2], [3; 4; 5])
wit the second one, you'll get:
# parse_list test_parse [1; 2; 3; 4; 5];;
- : int list * int list = ([], [3; 4; 5])