Here is the code on sorting any given list:
let rec sort lst =
match lst with
[] -> []
| head :: tail -> insert head (sort tail)
and insert elt lst =
match lst with
[] -> [elt]
| head :: tail -> if elt <= head then elt :: lst else head :: insert elt tail;;
[Source: Code
However, I am getting an Unbound error:
Unbound value tail
# let rec sort lst =
match lst with
[] -> []
| head :: tail -> insert head (sort tail)
and insert elt lst =
match lst with
[] -> [elt]
| head :: tail -> if elt <= head then elt :: lst else head :: insert elt tail;;
Characters 28-29:
| head :: tail -> if elt <= head then elt :: lst else head :: insert elt tail;;
^
Error: Syntax error
Can anyone please help me understand the issue here?? I did not find head or tail to be predefined anywhere nor in the code
Your code seems correct, and compiles for me:
Objective Caml version 3.11.1
# let rec sort lst = ...
val sort : 'a list -> 'a list = <fun>
val insert : 'a -> 'a list -> 'a list = <fun>
# sort [ 1 ; 3 ; 9 ; 2 ; 5 ; 4; 4; 8 ; 4 ] ;;
- : int list = [1; 2; 3; 4; 4; 4; 5; 8; 9]
Adding to what Pascal said, the list type is defined as:
type 'a list = [] | :: of 'a * 'a list
and that's what you are matching your list lst against.
The symbol “|“ is the horizontal line symbol, it is not l character and the -> are the minus symbol and the bigger symbol. I think you copied and pasted the segment of code in the website of Inria. Please check and rewrite the special symbols. I tested it and it works well.
Head and tail need not to be defined. They are matched from 'list' you give.
Related
Trying to insert a number in all positions of the list, result being a list of lists.
something like:
insert 4 [1; 2; 3] = [[4; 1; 2; 3]; [1; 4; 2; 3]; [1; 2; 4; 3]; [1; 2; 3; 4]]
My idea is to apply Map on the list with a function that returns a list.
resulting in list of lists. like [f 1; f 2 ; f3] (I know will only have 3 lists, but just want to get this working first)
let insert (x : 'a) (ls : 'a list): 'a list list =
let aux p =
List.fold_left
(fun f2 acc q ->
if p = q then List.append acc x::[q]
else List.append acc q::[])
[] ls
in
List.map aux ls
Hope is, function aux will return a list with x inserted in the right place.
The problem is, List.map f1 ls line is assuming ls is 'a list list even though it is defined as 'a list
Any ideas please?
To actually answer your question, instead of providing you with different methods to reach your goal (you wanted to know what is actually wrong with your code, not how one could solve the problem.):
signature of fold_left is ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a = <fun>. Instead of ('a -> 'b -> 'a) your provide it with fun f2 acc q -> ... = ('a -> 'b -> 'c -> 'a). Just remove the f2 and you're fine.
put brackets around stuff like x::[q], or use ##.
Your code:
let insert (x : 'a) (ls : 'a list): 'a list list =
let aux p =
List.fold_left
(fun f2 acc q ->
if p = q then List.append acc x::[q]
else List.append acc q::[])
[] ls
in
List.map aux ls
Working code:
let insert (x : 'a) (ls : 'a list): 'a list list =
let aux p =
List.fold_left
(fun acc q ->
if p = q then List.append acc (x::[q])
else List.append acc (q::[]))
[] ls
in
List.map aux ls
For input insert 4 [1;2;3]this returns int list list = [[4; 1; 2; 3]; [1; 4; 2; 3]; [1; 2; 4; 3]]. This is almost what you wanted. The rest can be fixed by you :).
Note:
The Error that the Compiler throws is: Error: This expression has type 'a list but an expression was expected of type 'b list -> 'b list list. For the next time, just think about what happened. You provide fold_left with ('a -> 'b -> 'c -> 'a); which is not "wrong", but not what you want. You could write it as ('a -> ('b -> 'c) -> 'a). This means the acc-value is some 'a and the value of the fold is a function 'b -> 'c. This explains the error-message :).
Try breaking this problem down.
First hurdle: can you insert an element at a given index in a list? The start might look like:
let rec insert lst pos v =
(* ... *)
Well, we know if the position is 0, it should go at the front.
let rec insert lst pos v =
match pos with
| 0 -> v :: lst
| _ -> (* ... *)
If it's not 0 then you'd need to append the first element in lst to the result of inserting into the tail of the list at pos - 1.
Of course, the devil is in the details. What happens if you try insert [1; 2; 3; 4] 7 5? You need to find a way to check for situations like this.
If you can get this function to work, you then just need to iterate from 0 to the length of the list, inserting the new value into the list.
List.init would work nicely.
List.(
let lst = [1; 2; 3; 4] in
let len = length lst + 1 in
init len (fun i -> insert lst i 5)
)
And as a result, if you wrote insert correctly, you should get:
[[5; 1; 2; 3; 4]; [1; 5; 2; 3; 4]; [1; 2; 5; 3; 4];
[1; 2; 3; 5; 4]; [1; 2; 3; 4; 5]]
This should do the trick:
let rec insert v l =
match l with
| [] -> [[v]]
| x::xs -> (v::l) :: (List.map (List.cons x) (insert v xs))
Adding an explanation, had to think about this a while too:
For an empty list there is only one way to insert v and [[v]] is the result.
For a list x::xs first insert v at all positions in xs: insert v xs, which gives a list of lists. Then for each list add x back to the front: List.map (List.cons x) .... This gives all the results where v is inserted after x. So last construct the list where v is added before x: v::l. Adding that to the front of the list of lists gives the final result.
I have to make a function that take a list and return the list but without the elements betweens the occurences.
For example: [1; 2; 3; 4; 2; 7; 14; 21; 7; 5] -> [1; 2; 7; 5]
I imagined that to make this I will take the head of the list, and then see
if there is another occurrence in the tail, so I browse the list and when I found the occurrence, I delete everything between them and I keep just one of them.
First I tried something like this:
let rec remove list = match list with
| [] -> []
| h::t -> if(List.mem h t) then
(*Here I would like to go through the list element by element to
find the occurence and then delete everything between*)
else
remove t
So for the part I don't succeed to do, I made a function which allows to slice a list between two given points, just like so:
let slice list i k =
let rec take n = function
| [] -> []
| h :: t -> if n = 0 then [] else h :: take (n-1) t
in
let rec drop n = function
| [] -> []
| h :: t as l -> if n = 0 then l else drop (n-1) t
in
take (k - i + 1) (drop i list);;
(*Use: slice ["a";"b";"c";"d";"e";"f";"g";"h";"i";"j"] 2 3;;*)
I also have this function that allows me to get the index of points in the list:
let index_of e l =
let rec index_rec i = function
| [] -> raise Not_found
| hd::tl -> if hd = e then i else index_rec (i+1) tl
in
index_rec 0 l ;;
(*Use: index_of 5 [1;2;3;4;5;6] -> return 4*)
But I don't really know how to combine them to get what I expect.
here is what I made :
let rec remove liste =
let rec aux l el = match l with
| [] -> raise Not_found
| x :: xs -> if el = x then try aux xs el with Not_found -> xs
else aux xs el in
match liste with
| [] -> []
| x :: xs -> try let r = x :: aux xs x in remove r with Not_found -> x :: remove xs;;
my aux function return the list which follow the last occurence of el in l. If you have any question or if you need more explanation just ask me in comment
A version that uses an option type to tell if an element appears further on in the list:
let rec find_tail ?(eq = (=)) lst elem =
match lst with
| x :: _ when eq x elem -> Some lst
| _ :: xs -> find_tail ~eq xs elem
| [] -> None
let rec remove ?(eq = (=)) lst =
match lst with
| [x] -> [x]
| x :: xs -> begin
match find_tail ~eq xs x with
| Some tail -> x :: remove ~eq (List.tl tail)
| None -> x :: remove ~eq xs
end
| [] -> []
Also lets you specify a comparison function (Defaulting to =).
As the title suggests, I want to use fold. If I understand correctly, it it used to apply a function to every item in a list. That's what I want to do with my function, but I don't know how to format it.
Here is the function I want to use with fold :
let pairing list =
let rec aux counter length paired list = match list with
| [] -> paired
| [head] -> paired
| head :: head' :: tail -> if counter = length then aux (counter-1) length ((head, head) :: paired) (head :: head' :: tail) else aux counter length ((head, head') :: paired) (head' :: tail)
in List.rev(aux (List.length(listheads list)) (List.length(listheads list)) [] (listheads list));;
What it does is it returns a list of all the items in the list paired together.
For example, if my list is [3;4;2], it should return
[(3,3); (3,4); (3,2); (4,3); (4,4); (4,2); (2,3); (2,4); (2,2)]
What it returns at the moment is only [(3,3); (3,4); (3,2)], because the function only applies to the first item of the list.
Here are all the helper functions :
let rec member list x = match list with
| [] -> false
| head :: tail -> head = x || member tail x
let head_list list =
let rec aux l1 list = match list with
| [] -> l1
| (x,y) :: tail -> aux (x :: l1) tail
in List.rev (aux [] list);;
let head'_list list =
let rec aux l2 list = match list with
| [] -> l2
| (x,y) :: tail -> aux (y :: l2) tail
in List.rev (aux [] list);;
let listheads list =
let rec aux returnlist l1 l2 = match l1 with
| [] -> returnlist
| head :: tail -> if member l2 head = true && member returnlist head = false then aux (head :: returnlist) tail l2 else aux returnlist tail l2
in List.rev(aux [] (head_list list) (head'_list list));;
What listheads does is it will take my original list (say [(3,4); (4,2); (2,3); (4,7); (9,4)]), use head_list and head'_list in order to determine which integers are both in head and head' position in the tuple, and put them in the list (in the case I gave, [3;4;2]).
I know that fold takes a function, an empty list and a list as arguments, but I don't know how to use pairing with fold.
Your code need to make a double pass on the list
let pairing l =
let second_pass x acc y = ...... in
let first_pass acc el = ....... in
List.fold_left first_pass [] l |> List.rev
The first pass function should call the second pass function, and the second pass function will create the pair element. Free to you for completing the code of the two functions.
Here the result I have :
utop # pairing [3 ; 4 ; 2];;
- : (int * int) list =
[(3, 3); (3, 4); (3, 2); (4, 3); (4, 4); (4, 2); (2, 3); (2, 4); (2, 2)]
It's very difficult to answer your question because there's no clean place to add a fold to get the result you want.
It might be more fruitful just to debug your code. It seems to me you're using your counter backwards. Its initial value is the length of the list and it is decremented for each recursive call. But your test for termination tests against the length of the list. It seems to me you should be testing against 0 (or possibly 1).
If you have a function f that does something interesting to a value, and you have a list of the values, you can use List.map to get a list of the values of f applied to each element of the list. You don't need a fold for that.
The purpose of a fold is to compute thing other than just a list of the function values. For examle, if each call to f makes a list of values, you could use a fold to keep concatenating these lists into a longer list.
Let's say f makes a value x into a list [x; x]. Then you can create a (reversed) doubled list something like this:
let f x = [x; x]
let double l =
let aux sofar x = f x # sofar in
List.fold_left aux [] l
# double [1;2;3];;
- : int list = [3; 3; 2; 2; 1; 1]
You could possibly follow this pattern if you can come up with a function like f that transforms a value into a list. If you define f inside your outer function it will have access to the initial list.
I have been trying one of the problems on 99 OCaml problems where you have to a have a list of all consecutive numbers in a list such as [2;3;4;4;5;6;6;6] -> [[2];[3];[4;4];[5];[6;6;6]]
let rec tail = function
| [] -> []
| [x] -> [x]
| x::xs -> tail xs;;
let pack lst =
let rec aux current acc = function
| [] -> current
| [x] -> if (tail acc) = x then (x::acc)::current
else [x]::current
| x::y::xs -> if (x=y) then aux current (x::acc) (y::xs)
else aux (acc::current) [] (y::xs)
in
aux [] [] lst;;
When i run this i get the error
Error: This expression has type 'a list
but an expression was expected of type 'a list list
The type variable 'a occurs inside 'a list
I was wondering what the problem is?
As Bergi pointed out (tail acc)=x is the problem. tail returns 'a list so x must also be of type 'a list. The following x::acc then infers that acc must be of type 'a list list. But tail acc infers acc as 'a list.
At this point OCaml can't unify the types of 'a list list and 'a list and gives the error you see.
I wanted to have a tail-recursive version of List.map, so I wrote my own. Here it is:
let rec list_map f l ?(accum=[])=
match l with
head :: tail -> list_map f tail ~accum:(head :: accum)
| [] -> accum;;
Whenever I compile this function, I get:
File "main.ml", line 69, characters 29-31:
Warning X: this optional argument cannot be erased.
The tutorial says that this means that I'm trying to create a function with no non-optional arguments. But the function above clearly takes non-optional arguments.
I'm probably just doing something really dumb, but what?
Yeah your non-optional argument can't be last, because since OCaml supports partial applications, a function missing a last optional argument will just look like a partially-applied function which is still looking for the optional argument. The only way for it to tell that you don't intend to provide the optional argument is that it sees that you have provided an argument after it.
If you have to have it last, you can put a dummy unit argument after it:
let rec list_map f l ?(accum=[]) () =
match l with
head :: tail -> list_map f tail ~accum:(head :: accum) ()
| [] -> accum;;
But in this case yeah changing the order would be better.
You need a non-optional argument after the optional one.
Just change the order of the arguments of your function:
let rec list_map f ?(accum=[]) l=
match l with
head :: tail -> list_map f ~accum:(head :: accum) tail
| [] -> accum;;
The previous solutions do compile, but won't give the expected result. The function f is never applied to the arguments. A correct code is:
let rec list_map f ?(accum = []) l = match l with
| head :: tail -> list_map f ~accum:(f head :: accum) tail
| [] -> accum;;
The inferred type is:
val list_map : ('a -> 'b) -> ?accum:'b list -> 'a list -> 'b list = <fun>
... in contrast to the wrong one:
val list_map : 'a -> ?accum:'b list -> 'b list -> 'b list = <fun>
Please note, that the result list is reversed:
# list_map ( ( ** ) 2.) [1.;2.;3.;4.];;
- : float list = [16.; 8.; 4.; 2.]
... and equals the function rev_list from the List module:
# List.rev_map ( ( ** ) 2.) [1.;2.;3.;4.];;
- : float list = [16.; 8.; 4.; 2.]
So you may want to change your function into:
let rec list_map f ?(accum = []) l = match l with
| head :: tail -> list_map f ~accum:(f head :: accum) tail
| [] -> List.rev accum;;
... which should be tail-recursive as well (according to the manual) and returns the list in the original order:
# list_map ( ( ** ) 2.) [1.;2.;3.;4.];;
- : float list = [2.; 4.; 8.; 16.]