F# : need help reversing order of ilist - list

I must use the following data type:
type ilist = E | L of int * ilist
I can't seem to find much help on working with lists outside of the standard type online ( [1;2;3] )
I am to write a function that takes a lists and reverses the order
for example: reverse (L(1, L(2, L(3, E)))) would output (L(3, L(2, L(1, E))))
So far here is my code:
let rec reverse l =
match l with
| E -> failwith "Empty List"
| L(h, E) -> h
| L(h, t) -> // append tail and recursive call with rest of list?
let list = reverse (L(1, L(2, L(3, E))))
printfn "reversed list: %A" list
Thanks for any help!

What you are lacking is a convenient way to append an int to an ilist:
let rec append x l =
match l with
| E -> L (x,E)
| L (h,t) -> L (h,append x t)
printfn "%A" (append 4 list)
Now use this function in your last match case to append h to the reversed t:
let rec reverse l =
match l with
| E -> E
| L (h,t) -> append h (reverse t)
Note that it's probably better to just return an empty list when the input list is empty (| E -> E), because failwith is something very ugly you should only use in the rarest cases.
Also note that your second match case | L(h, E) -> h is wrong, because it returns an int instead of an ilist. But it is not needed anyway, so just remove it. The singleton list L (h,E) will be matched with | L (h,t) -> ... instead, which in turn recursively matches t with | E -> E.
Here is a working example: https://repl.it/repls/PhonyAdventurousNet

Related

Tail call optimization with a function returning a tuple

I have a simple function that splits a list at an index:
let rec split_at ls i =
match i with
| 0 -> ([], ls)
| _ ->
match ls with
| [] -> raise Not_found
| h::t ->
match split_at t (i - 1) with
| (left, right) -> ((h :: left), right)
Is there a way to get the OCaml compiler to optimize this function to use constant stack space?
I have tried using #tail_mod_cons but it doesn't work. I understand that the call is not really in tail position, but it feels like it should be optimizable.
Firstly, let's clean up your function by pattern matching on a tuple of i and ls and using a local let binding rather than that last match expression.
let rec split_at ls i =
match i, ls with
| 0, _ -> ([], ls)
| _, [] -> raise Not_found
| _, h::t ->
let (left, right) = split_at t (i - 1) in
(h::left, right)
As Jeffrey says, the cons (::) is not in tail call position, so tail_mod_cons does nothing for you. If we try to use it, we'll get a warning to that effect:
Lines 1-7, characters 33-20:
Warning 71 [unused-tmc-attribute]: This function is marked #tail_mod_cons
but is never applied in TMC position.
As also hinted, though, it's trivial to let your brain modify this for tail-recursion using an accumulator.
let split_at lst n =
let rec aux lst n first_part =
match n, lst with
| 0, _ -> (List.rev first_part, lst)
| _, [] -> raise Not_found
| _, h::t -> aux t (n - 1) (h::first_part)
in
aux lst n []
The function split_at can be written in a partial tail_mod_cons way if we split the construction of the new prefix from the part of the function returning the suffix using a reference:
let[#tail_mod_cons] rec split_at r ls i =
match i with
| 0 -> r := ls; []
| _ ->
match ls with
| [] -> raise Not_found
| h::t ->
h:: (split_at[#tailcall]) r t (i - 1)
let split_at ls i =
let r = ref [] in
let l = split_at r ls i in
l, !r
The way I understand it, "tail mod cons" works by passing an incomplete constructor into which the called function should place its answer. So to make the optimization work you have to be able to put your problem into a form for which this is a solution.
Maybe it would work if you split the problem into two parts. The first part duplicates the first n elements of the list. The second part returns all but the first n elements of the list.
The second part is trivial to implement tail recursively. And it seems like you should be able to duplicate a list using "tail mod cons".

Create a list with data extracted from a list of tuples - type issue

My data is ordered like this:
([(x1,y1,z1);(x2,y2,z2);(x3,y3,z3);........;(xn,yn,zn)], e:int)
Example: I try to create a list [x1;x2;x3;....;xn;e] where a value is found only once.
I began the following code but I encounter an issue with type.
let rec verifie_doublons_liste i liste = match liste with
| [] -> false
| head::tail -> i = head || verifie_doublons_liste i tail
let rec existence_doublon liste = match liste with
| [] -> false
| head::tail -> (verifie_doublons_liste head tail) ||
existence_doublon tail
let premier_du_triplet (x,y,z) = x
let deuxieme_du_triplet (x,y,z) = y
let troisieme_du_triplet (x,y,z) = z
let rec extract_donnees l = match l with
| [] -> []
| (x,y,z)::r -> (extract_donnees r)##(x::z::[])
let arrange donnees = match donnees with
| [],i -> i::[]
| (x,y,z)::[],i -> x::z::i::[]
| (x,y,z)::r,i -> (extract_donnees r)##(x::z::i::[])
Basically, you want to extract first elements in a list of tuples, and add the e elemnent at the end.
The easiest way is to use a List.map to extract the first elements
List.map premier_du_triplet
is a function that will take a list of 3-tuples and extract the first element of each.
then you can add the e element at the end using the "#" operator.
The more efficient and informative way would be to directly write a recursive function, say f that does just what you want.
When writing a recursive function, you need to ask yourself two things
what does it do in the simplest case (here, what does f [] do ?)
when you have a list in format head::tail, and you can already use f on the tail, what should you do to head and tail to obtain (f (head::tail)) ?
With this information, you should be able to write a recursive function that does what you want using pattern matching
here the simplest case is
| [] -> [e]
(you just add e at the end)
and the general case is
| h::t -> (premier_de_triplet h)::(f t)

What is wrong with this OCAML function?

Here is my original code.
let rec reverse l =
match l with
| [] -> []
| (h::t) -> (reverse t) :: h
The cons :: operator takes an element as left-hand argument and a list as right-hand argument. Here, you do the opposite which does not work.
The right way to add an element at the element at the end of a list is to use list concatenation:
let rec reverse l =
match l with
| [] -> []
| h :: t -> (reverse t) # [h]
That code is not optimal though, and you may want to make it tail recursive.

pairing an int with a list of ints in OCaml

I am using OCaml to write a function that takes a list of ints and an int element and returns a list of pairs where the first element of every pair is the int element and the second element of the pair is a member from the list. For example, let say I have the number 1 and the list [10; 20; 30] as inputs. I like the function to return [(1, 10); (1, 20); (1, 30)]. I wrote the following function:
let rec f (lst : int list) (elm : int) : (int*int) list =
match lst with
| [] -> failwith "empty list"
| [x] -> [(x, elm)];;
I am getting the following error:
Characters 59-120:
Warning 8: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
_::_::_ val f : int list -> int -> (int * int) list = <fun>
What am I missing?
Here is your code
let rec f (lst : int list) (elm : int) : (int*int) list =
match lst with
| [] -> failwith "empty list"
| [x] -> [(x, elm)]
In your match, you listed two cases: [] and [x].
Your first case is [], you mean empty, no problem.
Your second case is [x], what did you want to mean? In OCaml, it means a list with only one element.
How about the cases where there are more than one element?
For any if else or match with, you should include all cases.
When you fix this problem, you will soon find you really missed something more there.
Here is the correct code:
let rec f e l =
match l with
| [] -> []
| x::[] -> [(e,x)]
| x::tl -> (e,x)::(f e tl)
Note
above code is not tail-recursive and you normally should consider about it, I will leave that to you.
you don't need ;; if you write your code in file and compile the file
You don't need to declare types in most cases and that is one of the best thing ocaml has.
Your patterns match lists of length 0 ([]) and of length 1 ([x]). The compiler is telling you that there are other lengths that a list might have, so your pattern is probably wrong (which is true).
I might note that it's not an error to get an empty list as an argument. Thinking this way will make it much harder to answer the problem. If you get an empty list, the correct answer is an empty list of pairs.
let rec f e = function
| [] -> []
| x::tl -> (e,x)::f e tl
Or
let f e = List.map (fun x -> (e,x))
Test
# f 1 [];;
- : (int * 'a) list = []
# f 1 [10;20;30];;
- : (int * int) list = [(1, 10); (1, 20); (1, 30)]

Find unique elements in a list in OCaml

I am working on a project with OCaml and there are some problems regarding to arrays that I am not sure with. I am not allowed to use the List module, so please give me some idea or suggestion with my works.
First, I already implemented a function 'a list -> 'a list called uniq that return a list of the uniq elements in an array, for example uniq [5;6;5;4] => [6;5;4]
Here is my implementation:
let rec uniq x =
let rec uniq_help l n =
match l with
[] -> []
| h :: t -> uniq_help t, n if (n = h) else (h :: (uniq_help(t, n)))
match x with
[] -> []
| h::t -> uniq_help t, h
;;
I mot sure this is a correct implementation, can someone give me some suggestion or correctness?
You functions are syntactically incorrect for various reasons:
uniq_help takes two elements so you have to invoke it using uniq_help t n, not uniq_help(t, n) and the like.
an if/else expression should have the form of if cond then expr1 else expr2.
to use uniq_help locally in uniq, you need an in keyword.
After fixing syntax errors, your function looks like:
let rec uniq x =
let rec uniq_help l n =
match l with
| [] -> []
| h :: t -> if n = h then uniq_help t n else h::(uniq_help t n) in
match x with
| [] -> []
| h::t -> uniq_help t h
However, to be sure that each element is unique in the list, you have to check uniqueness for all of its elements. One quick fix could be:
let rec uniq x =
(* uniq_help is the same as above *)
match x with
| [] -> []
| h::t -> h::(uniq_help (uniq t) h)