OCaml assertion fail - ocaml

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

Related

Why do i get syntax error at end problem with pattern matching

I have to make a function that takes list a list and returns list of pairs of first and last element,2nd and 2nd last and so forth It doesn't matter if the list has even or odd number of elements because if its odd i will just ignore the middle element.The idea i have is that make a new rec fun that takes old list and its revers as input i think i finished the code but i get Syntax error for ;;
let lip l =
if [] then []
else let l1=l l2=List.rev l in
let rec lp l1 l2 = match l1,l2 with
| [],[] ->[]
| [],h2::t2->[]
| h1::_,h2::_ ->
if (List.length l -2) >= 0 then [(h1,h2)]# lp(List.tl l1) t2
else [] ;;
There are quite a few errors in your code.
I think the specific error you're seeing is caused by the fact that there is no in after let rec lp ....
Every let that's not at the top level of a module needs to be followed by in. One way to think of it is that it's a way of declaring a local variable for use in the expression that appears after in. But you need to have the in expr.
Another way to look at it is that you're defining a function named lp but you're not calling it anywhere.
As #lambda.xy.x points out, you can't say if [] then ... because [] isn't of type bool. And you can't say let x = e1 y = e2 in .... The correct form for this is let x = e1 in let y = e2 in ...
(Or you can write let x, y = e1, e2 in ..., which looks nicer for defining two similar variables to two similar values.)
The following code should at least compile:
let lip list1 =
if list1 = [] then []
else
let list2=List.rev list1 in
let rec lp l1 l2 = match l1,l2 with
| [], [] ->[]
| [], _::_->[]
| h1::_::_, h2::t2 -> (* l1 length >= 2*)
(h1,h2) :: lp(List.tl l1) t2
| h1::_,h2::t2 -> (* l1 length = 1 *)
[]
in
[]
I have made the following changes:
renamed the arguments of lip to make clear they are different from the arguments of lp
removed the alias let l1 = l
changed the if condition to a term of type boolean -- there's not much to compare, so I assume you are checking list1
replaced the list length condition by a pattern match against two heads
the else path is the second match - it might be better to rewrite that one to | [h1, _] -> ...
the definition of lp needs to be followed with the actual body of lip - to make it compile, we just return [] at the moment but you probably would like something else there
As #Jeffrey Scofield already mentioned, you are not using lp in your code. It could help if you added a comment that explains what you'd like to achieve and what the intended role of lp is.

ocaml 'a list list function tuples

let sample_table4 = [
[["11"];["21"];["31"];["41"]];
[["12"];["22"];["32"]];
[["13"];["23"]];
[["14"]]];;
This is where I'm stuck with writing a function to get one of these numbers
let tgvc (pos, table) =
match pos with
|[] -> []
|i::[j] -> List.nth (List.nth table (j-1)) (i-1)
|i::_ -> []
;;
val tgvc : int list * 'a list list list -> 'a list = <fun>
I'm supposed to get this signature
tgvc ([3;2],sample_table4);;
val tgvc : int list * ’a list list -> ’a = <fun>
-: string list = ["32"]
What's missing in the function?
I'm sure it has to be recursive now.
Even though it computes the right answer, it's not the right method. The ->[ ] is what's getting me
let rec tgvc (pos, table) = function
|_,[] -> []
|[i;1], h::_ -> List.nth h (i-1)
|[i;j], _::t -> tgvc ([i;j-1], t)
|_ -> []
|[i;j], _::t -> tgvc ([i;j-1], t)
^^^^^^^^^^^^^^^^^
Error: This expression has type int list * 'a list list list -> 'a list
but an expression was expected of type 'a list
What's missing in the function?
A lot of things. Your function simply returns one of many lists of initial input. You don't even use i indice.
I suggest you to think what your function need to do for the given input:
[i; 1], h::_ - you are "in front" of the desirable list
[i; j], _::t - not desirable list yet (some recursion maybe?)
_, [] - empty table
_ - everything else
Edit
You have two problems with your last implementation. First of all in your first and last branches you return [], I guess you would like to exit with an error, so you can throw an exception (via failwith for example). The second problem is actually in the first line: get_table_values_cell (pos, table) = function, it means that you define get_table_values_cell as function with two arguments, you give one explicitly ((pos, table)) and the second is introduced by function keyword. So all you need is to pick only one: get_table_values_cell = function

K out on N implementation - SML

I was trying to implement k-out-of-N at SML so "pick(3,[1,2,3,4])" will return [[1,2,3],[1,3,4]...] (all the K-size picks out of N elements)
I used List.map which I figured it calls the function and apply it on each element.
Really can't figure out why when typing the input "pick(3,[1,2,3,4,5])" ,for example, it return an empty list.
My first thought was that it's because of the initial terms (choose (_,[]) = [])
But changing it didn't work as well.
The signature is ok (val pick = fn : int * 'a list -> 'a list list).
fun pick (_,[]) = []
| pick (0,_) = []
| pick (n,hd::tl) =
let
val with_hd = List.map (fn x => hd::x) (pick(n-1,tl))
val without_hd = pick(n,tl)
in
with_hd#without_hd
end;
The problem is related to your suspicion – the base cases are incorrect in that they always produce the empty list, and mapping fn x => hd::x onto the empty list produces the empty list.
Picking zero elements from anything should succeed, and produce the empty list.
That is, pick (0, _) = [[]] — a list with one element, which is the empty list.
You also need to rearrange the cases since pick(n, []) succeeds for n = 0 but not for any other n.
In summary,
fun pick (0, _) = [[]]
| pick (_, []) = []
with the rest of the function exactly as before.

OCaml: remove the first element of a list

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

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)]