rev function of n-dimensional lists - list

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?

Related

List.assoc using List.find

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.

Filtering integers from list of list in OCaml

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.

OCaml code consecutive list creation simple code

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.

Function to flatten `('a list * b' list) list` to `'a list* 'b list` in OCaml

I need a function in OCaml that will take a type of
('a list * b' list) list and make of it
'a list * b' list. I have tried with the built in functions List.flatten and List.concat but they do not work, they require a type of 'c list list. Can someone help me?
You have to use the functions List.split and List.flatten:
let my_function l =
let (fst_list, snd_list) = List.split l in
List.flatten fst_list, List.flatten snd_list ;;
First the split function will generate and 'a list list and a 'b list list, then you just have to flatten them.
You can do it using the function fold_left like this :
You start with two empty lists working as accumulators. For every sub-lists in your the input list, you add the elements into the respective accumulator (elements of the first sub-list in the first accumulator and same thing for the second sub-list).
# let flatten l =
let (l1,l2) =
List.fold_left (fun (l1,l2) (x,y) ->
(x :: l1, y :: l2)) ([], []) l in
List.rev (List.flatten l1), List.rev (List.flatten l2);;
val flatten : ('a list * 'b list) list -> 'a list * 'b list = <fun>
#
Unfortunately there is no map for tuples and you need to decompose - e.g. using using split and flatten:
let splcat x = match List.split x with | (a,b) -> (List.flatten a, List.flatten b) ;;
That's how it looks on the commandline:
utop # splcat [([1;2],["a"]); ([3],["uvw";"xyz"]) ] ;;
- : int list * bytes list = ([1; 2; 3], ["a"; "uvw"; "xyz"])
The following should work:
let split2 l = (List.map fst l, List.map snd l)
let flatten2' (l1, l2) = (List.flatten l1, List.flatten l2)
let flatten2 l = flatten2' (split2 l)
Here, split2 will turn a ('a list * 'b list) list into a ('a list list * 'b list list) (fst and snd return the first and second component of a pair, respectively) and flatten2' will individually flatten the two components. And flatten2 will finally do what you require. You can also pack this into a single function, but I think this is easier to understand.
Note that neither List.map nor List.flatten is tail-recursive; if you need tail-recursive versions, there are other libraries that have them, or you can build them from the standard library using rev_xxx functions or write them from scratch.

OCaml - Need some help at implementing my rev function

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