I've got an assignment where I have to recode a big part of the different functions found on "list". I'm currently having trouble implementing the rev function.
type 'a my_list =
| Item of ('a * 'a my_list)
| Empty;;
This is the type of lists we are allowed to use and here is my attempt at doing it:
let rev my_list =
let rec rev_list list = function
| Empty -> list
| Item (first, rest) -> rev_list (Item (first, list))
rest in rev_list Empty;;
rev function has for prototype:
'a list -> 'a list:
and this is what I'm getting:
'a -> 'b my_list -> 'b my_list
Any pointers?
EDIT: Well, right as I posted the question I found the answer, if it might help anybody, here it is
let rev my_list =
let rec rev_list list = function
| Empty -> list
| Item (first, rest) -> rev_list (Item (first, list))
rest in rev_list Empty my_list
Related
I want to implement the List.assoc function using List.find, this is what I have tried:
let rec assoc lista x = match lista with
| [] -> raise Not_found
| (a,b)::l -> try (List.find (fun x -> a = x) lista)
b
with Not_found -> assoc l x;;
but it gives me this error:
This expression has type ('a * 'b) list but an expression was expected of type 'a list
The type variable 'a occurs inside 'a * 'b
I don't know if this is something expected to happen or if I'm doing something wrong. I also tried this as an alternative:
let assoc lista x = match lista with
| [] -> raise Not_found
| (a,b)::l -> match List.split lista with
| (l1,l2) -> let ind = find l1 (List.find (fun s -> compare a x = 0))
in List.nth l2 ind;;
where find is a function that returns the index of the element requested:
let rec find lst x =
match lst with
| [] -> raise Not_found
| h :: t -> if x = h then 0 else 1 + find t x;;
with this code the problem is that the function should have type ('a * 'b) list -> 'a -> 'b, but instead it's (('a list -> 'a) * 'b) list -> ('a list -> 'a) -> 'b, so when I try
assoc [(1,a);(2,b);(3,c)] 2;;
I get:
This expression has type int but an expression was expected of type
'a list -> 'a (refering to the first element of the pair inside the list)
I don't understand why I don't get the expected function type.
First off, a quick suggestion on making your assoc function more idiomatic OCaml: have it take the list as the last argument.
Secondly, why are you attempting to implement this in terms of find? It's much easier without.
let rec assoc x lista =
match lista with
| [] -> raise Not_found
| (a, b) :: xs -> if a = x then b else assoc x xs
Something like this is simpler and substantially more efficient with the way lists work in OCaml.
Having the list as the last argument, even means we can write this more tersely.
let rec assoc x =
function
| [] -> raise Not_found
| (a, b) :: xs -> if a = x then b else assoc x xs
As to your question, OCaml infers the types of functions from how they're used.
find l1 (List.find (fun s -> compare a x = 0))
We know l1 is an int list. So we must be trying to find it in an int list list. So:
List.find (fun s -> compare a x = 0)
Must return an int list list. It's a mess. Try rethinking your function and you'll end up with something much easier to reason about.
I am trying to write a function that filters positive integers from a list of list of integers, returning a list of only negative integers.
For example, if I have a list of list such as [[-1; 1]; [1]; [-1;-1]] it would return [[-1]; []; [-1;-1]].
I tried to use filter and transform functions, which was in my textbook.
let rec transform (f:'a -> 'b) (l:'a list) : 'b list =
begin match l with
| [] -> []
| x::tl -> (f x)::(transform f tl)
end
and for filter, I had previously written:
let rec filter (pred: 'a -> bool) (l: 'a list) : 'a list =
begin match l with
| [] -> []
| x :: tl -> if pred x then x :: (filter pred tl) else filter pred tl
end
So, using these, I wrote
let filter_negatives (l: int list list) : int list list =
transform (fun l -> (filter(fun i -> i<0)) + l) [] l
but I'm still having trouble fully understanding anonymous functions, and I'm getting error messages which I don't know what to make of.
This function has type ('a -> 'b) -> 'a list -> 'b list
It is applied to too many arguments; maybe you forgot a `;'.
(For what it's worth this transform function is more commonly called map.)
The error message is telling you a simple, true fact. The transform function takes two arguments: a function and a list. You're giving it 3 arguments. So something must be wrong.
The transformation you want to happen to each element of the list is a filtering. So, if you remove the + (which really doesn't make any sense) from your transforming function you have something very close to what you want.
Possibly you just need to remove the [] from the arguments of transform. It's not clear (to me) why it's there.
I am currently working on a function, that computes the difference of the two lists in the following way.
The input lists are sorted by the value of the key of type 'a.
The result includes the pairs from the first list with the keys
that are not included in the second list.
Example:
diff [(1,2);(2,3);(4,5)];(5,6)] [(2,4);(4,6)] → [(1,2);(5,6)]
Now I am facing Error, I can't solve.
My code:
let rec diff list1 list2= match list1,list2 with
|x,[] -> [x]
| [],_->[]
| h1::t1,h2::t2 ->
let (k1,v1) = h1 in
let (k2,v2)=h2 in
if(k1=k2) then diff t1 t2
else if (k1>k2) then h1::(diff list1 t2)
else h2::(diff t1 list2)
ERROR message:
else if (k1>k2) then h1::(diff list1 t2) Error: This expression has
type 'a * 'b
but an expression was expected of type ('a * 'b) list#
Working code:
let rec diff list1 list2= match list1,list2 with
|_,[] -> list1
| [],_->[]
| h1::t1,h2::t2 ->
let (k1,v1) = h1 in
let (k2,v2)=h2 in
if(k1=k2) then diff t1 t2
else if (k1>k2) then h1::(diff list1 t2)
else h1::(diff t1 list2)
Thanks for the answers.
When list2 is empty, you return a list of lists containing list1 (a.k.a. x). This tells OCaml that the return type is a list of lists of what the input lists contain. So when you later try to return just plain lists of tuples, rather than lists of lists of tuples, OCaml thinks that's the mistake.
But in fact returning a list of tuples is what you want. The mistake is returning a list of lists in the x, [] case. You can fix that by changing that case to | x, [] -> x or | _, [] -> list1.
I'm trying to make a function that take some list of type 'a list, where 'a could be of type 'b list, and 'b could be of type 'c list and so forth. it should revert every list in the list so that if 'a is a list then 'a should also be reverted and so forth.
let RevAll xs =
let rec rev acc = function
| (_::_)::__ as M -> rev ((rev List.Empty List.head M)::acc) (List.tail M)
| x::xs -> rev (x::acc) xs
| [] -> acc
rev List.Empty xs
Vs' compiler can't determent the types so it don't work. My question is as follow. Is there a way to make a function in F# that take an n-dimensional list and revert every dimension in that list without specifying the dimension?
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.