I have a list composed by several couples of numbers:
[(1,2);(3,4);(5,6);(7,8)]
I want to remove the the first element (the head) from the list, so the output should be:
[(3,4);(5,6);(7,8)]
Someone can help me? I was thinking about this function but it doesn't work:
let cut x = function
[] -> []
| (a,b) -> []
| (a,b)::ris -> ris
Just remember, that
let f x y = function -> <code>
is really a shortcut (or a syntactic sugar), for:
let f x y z = match z with -> <code>
So, it just cuts the last argument in a function, and automatically matches on it.
Also, when you pattern matching keep in mind, that all expressions in the left side of pattern match should have the same type. Otherwise, compiler may pick a random one, and decide, that all others have the same type, yielding a somewhat confusing error message. The same is true for the right sides of patter match. So, when you see a compiler message, saying that something is not what he has expected, just check this preconditions:
| [] (* is a list, by definition *)
| (a,b) -> [] (* is a pair, by definition of a pair *)
| (a,b)::ris -> ris (* is a list, by definition of (::) *)
If left part works, look at the right.
Also, if you have a variable that you do not need to use, then you should better give it a name starting with underscore, or just an underscore.
let cut = function
| [] -> []
| _::xs -> xs
You are almost there:
let tl x = match x with
| [] -> [] (* or failwith "empty" *)
| ab::ris -> ris
Few points:
function takes another argument. Your function already get one arg, so use match x with instead.
You are interested only in the list is empty or has a "tail", so you need not pattern-match its element as a tuple.
This function is called "tail", in OCaml, known as List.tl.
You could write simple:
let cut = List.tl
You have little mistake.
Third line should look like
| [(a,b)] -> []
or
| (a,b) :: [] -> []
P.S. by the way, this third line is unnecessary. Just remove it.
And delete x in first line:
let cut = function
Related
Hey everyone I'm new to OCaml and having some problems. So I'm trying to do a recursive function that takes a non-empty list and returns the last element. My list can be any data type though.
Here is what I have right now and it's currently failing on the assertion statement saying "This expression has type int but an expression was expected of type int list.
let rec last l = match l with
[] -> []
|[x] -> [x]
|_::t -> last t ;;
assert(last [1; 2; 3; 4] = 4);;
assert(last ["a"; "b"; "c"; "d"] = "d");;
I often find that a good way to deal with this kind of type errors, is to explicitly annotate the function with the type I want it to have - in this case, I expect that you want the first line to be something like this:
let rec last: 'a list -> 'a = fun l -> match l with
With that, the error changes to:
File "1/hest.ml", line 5, characters 9-10:
5 | |[x] -> [x]
^
Error: This expression has type 'a list
but an expression was expected of type 'a
The type variable 'a occurs inside 'a list
Which is a more helpful error. The problem is, as #PatJ writes in his answer, that as you have written the function you actually return a list with one element (or no elements, when the list is empty), but your usage of the function seems to indicate that you just want the last element.
You can either:
change your usage of the function, so the asserts compare with [4] and ["d"] instead of just the values.
change the function to return Some x and None instead of [x] and [], and change the asserts to assert against Some 1 and Some "d".
change the function to return x instead of [x] and throw an exception in the empty list case - that would be: failwith "empty list"
I think the second solution is the most natural one.
If you go for exceptions, then renaming the function to last_exn would convey to users that they have to beware that the function might throw.
The problem comes from the fact that your function is indeed returning a list, as can be seen in those two lines:
[] -> []
|[x] -> [x]
You want the second line to be |[x] -> x. Of course, you also need to handle the case of an empty list and effectively return something. You can either have it raise an exception, use an option type or have the caller specify a default value.
In this kind of cases, it's better to use an option type:
let rec last_opt l =
match l with
| [] -> None
| [x] -> Some x
| _x::t -> last_opt t
let () =
assert (last_opt [1; 2; 3; 4] = Some 4);
assert (last_opt ["a"; "b"; "c"; "d"] = Some "d"); (* Note that here you could use chars, i.e. 'a', 'b' etc. instead of strings "a", "b" etc. *)
assert (last_opt [] = None)
If you really don't want an option type, you should handle the empty case with care :
let rec last l =
match l with
| [] -> raise (Failure "last")
| [x] -> x
| _x::t -> last t
I have just started my F# adventure and am stuck. I want to write a recursive function that takes the elements from a list, add them in pairs and returns the list - int list->(int*int) list
So like this:
[x1; x2; x3; x4] = [(x1,x2);(x3,x4)]
This is what I have right now.
let rec combinePair xs =
match xs with
|[] -> []
|[x] -> [x]
|x::y::xs' -> (x,y)::combinePair xs'
This does not work, but I feel it may be close to the answer. I just don't how to continue from here. As I am still trying to learn I hoped that maybe one could point me in the right direction instead of giving me the full answer
Cheers
I was very close to the answer. I forgot to add what would happen in cases of the list containing an odd number of elements. In my case I just wanted it to get rid of the last element. This is the solution
let rec combinePair xs =
match xs with
| [] -> []
| [x] -> []
| x::y::xs' -> (x,y)::combinePair xs'
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)
let rec (l:int list) f int list =
match l with
| [] -> []
| hd::tl -> 2+tl
I want to know is hd the first element and then tl is the second element because when i do this I keep getting an error, if tl is not the second element how would i access the second element an in depth explanation of hd::tl would be highly appreciated thank you
No tl is not the second element, it is the rest of the list and it has type 'a list. Here hd and tl are just variable names that you choose to bind to the first element of a list, and to the rest of the list (i.e., to a list that contains all elements except the first one). You can choose other names, e.g., fst::rest. Getting the second element, in that case would be as easy as fst::snd::rest (or x::y::rest - again the name doesn't matter).
What you're trying to use is called pattern matching. It is a feature of some languages, that provides a mechanism to easily deconstruct compound data structures. The idea is that if you're deconstructing data structures the same way as you're constructing them, e.g,
let xs = [1;2;3;4]
and here is the deconstructing
let [x1;x2;x3;x4] = xs
In fact, [x;y;...;z] is a syntactic sugar for a more basic syntax x :: y:: ... :: z :: [], so another way to construct the [1;2;3;4] list is to use the following construct: 1::2::3::4::[]. The same works in the opposite direction, e.g.,
let x1::x2::x3::x4::[] = xs
Now we are ready to the next step, what if the structure on the right doesn't match the structure on the left, e.g.,
let [x;y;z] = [1;2]
or
let x::y::z::[] = 1::2::[]
In that case, the matching will fail. In our case in runtime. To prevent this, and to allow programmers to handle all possible configuration of their data structures OCaml provides the match construct in which you specify multiple variants of the value structure, and the first one that matches is chosen, e.g.,
let orcish_length xs = match xs with
| [] -> 0
| x :: [] -> 1
| x :: y :: [] -> 2
| x :: y :: z :: [] -> 3
The function above anticipates only lists that have up to three elements (because Orcs can't count beyond three). But we can. For this we will use the following feature -- if the last element of the list pattern is not [] (that is matches only and only with the empty list, and designates the end-of-list), but anything else (i.e., a variable), then this variable will be bound to all elements, e.g.,
let rec elvish_length xs = match xs with
| [] -> 0
| x :: [] -> 1
| x :: y :: [] -> 2
| x :: y :: z :: [] -> 3
| x :: y :: z :: leftovers -> 3 + elvish_length leftovers
So now, we anticipate all possible list patterns. However, the function is now overcomplicated (because Elves are complicating). Now, let's finally derive a normal, human readable, length function,
let rec length xs = match xs with
| [] -> 0
| x :: xs -> 1 + length xs
As an exercise, try to prove to yourself that this function anticipates all possible lists.
:: is read cons and is an infix version of List.cons. In a functional language like Ocaml, list is a linked list where i.e.[e1; e2; e3; e4] can be reduced to something like this:
cons(::)
/ \
e1 cons(::)
/ \
e2 cons(::)
/ \
e3 cons(::)
/ \
e4 [ ]
Basically, any list can be reduced to a tree of recursive cons expressions, which makes recursion so useful in Ocaml or similar functional languages. At each level, you can reduce a list to its head and its tail, where tail is the list minus its head and can be reduced further until last :: []. So with the above example, you can recursively reduce the list until you find the last element by pattern-matching:
let find_last li =
match li with
| [] -> None (* no element *)
| [last] -> Some last (* found last *)
| head :: tail -> find_last tail (* keep finding *)
;;
Note that [last] can be replaced with last::[] and head::tail with List.cons head tail. What is important is at any point a list can always be reduced to head :: tail, where head is the first element and tail is the list without head.
Pattern-matching is useful in matching the "shape" or state of the reducing list.
I have these these two functions
//Remove all even indexed elements from a list and return the rest
let rec removeEven l =
match l with
| x0::x1::xs -> x1::removeEven (xs)
| [] -> []
| [_] -> []
//combine list members into pairs
let rec combinePair l =
match l with
| x0::x1::xs -> (x0,x1) :: combinePair(xs)
| [] -> []
| [_] -> []
That work.
But I thought now that I was at it that I might as well learn a bit about tail recursion which I'm having a hard time getting the grasp of.
That's why I thought that if I could get some help making functions I had made myself tail-recursive perhaps it would become more clear how it works, instead of reading an example somewhere which I might not understand as well as my own code (remember, I'm a complete f# newbie :))
Any other constructive comments about my code are of course most welcome!
A typical way of making functions tail-recursive in F# is using a list (acc in this case) to accumulate results and reversing it to get the correct order:
let removeEven l =
let rec loop xs acc =
match xs with
| [] | [_] -> acc
| _::x1::xs' -> loop xs' (x1::acc)
loop l [] |> List.rev
let combinePair l =
let rec loop xs acc =
match xs with
| [] | [_] -> acc
| x0::x1::xs' -> loop xs' ((x0, x1)::acc)
loop l [] |> List.rev
Since we simply return results after each recursive call of loop, these functions are tail-recursive.
Your functions look quite nice, but I still have several comments:
Indentation is important in F#. I would prefer match... with is a few spaces behind lec rec declaration.
Patter matching cases should follow a consistent order. It's a good idea to start with base cases first.
The function keyword is natural to use for shortening functions whenever you have a pattern of fun t -> match t with.
It's better to get rid of unnecessary parentheses, especially in functions with one argument.
Applying above comments, your functions become as follows:
// Remove all even indexed elements from a list and return the rest
let rec removeEven = function
| [] | [_] -> []
| _::x1::xs -> x1::removeEven xs
// Combine list members into pairs
let rec combinePair = function
| [] | [_] -> []
| x0::x1::xs -> (x0, x1)::combinePair xs
If you need a slower, less maintainable way to do it that uses more memory, you can use a continuation.
let removeEven items =
let rec loop f = function
| _::h::t -> loop (fun acc -> f (h::acc)) t
| [] | [_] -> f []
loop id items
But hey, it's tail-recursive.