Reverse Mutable List Ocaml - list

I need to write a function that takes two mutable lists as input and as an output has the first list reversed appended to the second list. The type definition is:
type 'a mylist = 'a listcell ref
and 'a listcell = Nil | Cons of 'a * ('a mylist)
I am aware how to reverse a regular list but am having some confusion on writing a function that does this by destructively changing the first list.
Here is what I have but I keep getting a type error:
let rec rev_app l1 l2 =
let rec rev_app' l3 l4 =
match !l1 with
| Nil -> l2
| Cons (x,t) -> ref (rev_app t (Cons(x,l4)))
in rev_app' l1 l2

Your inner call to is to rev_app, not to rev_app'. So your code is somewhat similar to saying:
let rec f x = ref (f x)
As a side comment, it is good manners to quote the actual error you're getting. Just saying "a type error" isn't so helpful.

Related

Can I simplify this recursive concat function using List.fold_left?

I have created a working solution for concat, but I feel that I can reduce this using List.fold_lift.
Here is my current code:
let rec concat (lists : 'a list list) : 'a list =
match lists with
| [] -> []
| hd :: tl -> hd # concat tl ;;
Here is what I have tried:
let concat (lists : 'a list list) : 'a list =
List.fold_left # lists ;;
This gives me the error: This expression has type 'a list list but an expression was expected of type
'a list
I think this is because the return value of list.fold_left gives us a list, but we are feeding it a list of lists so it then returns a list of lists again. How can I get around this without matching?
I was also playing around with List.map but with no luck so far:
let concat (lists : 'a list list) : 'a list =
List.map (fun x -> List.fold_left # x) lists ;;
Consider the type signature of List.fold_left:
('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
List.fold_left takes three arguments.
A function.
An initial value.
A list to iterate over.
List.fold_left # lists
You're making two mistakes.
First off, this parses as (List.fold_left) # (lists).
You're looking for List.fold_left (#) lists. But that's still not quite right, because...
You're only passing two arguments, with lists being the initial value, while List.fold_left expects three.
I think that you're looking for something like:
let concat lists = List.fold_left (#) [] lists
Demonstrated:
utop # let concat lists = List.fold_left (#) [] lists in
concat [[1;2;3]; [4;5;6]; [7;8;9]];;
- : int list = [1; 2; 3; 4; 5; 6; 7; 8; 9]
It is possible to write concat as fold_left while avoiding quadractic complexity by switching temporarily to different representation of list
If I have a list l, I can easily lift into an append function:
let to_append l = fun new_list -> l # new_list
I can also get back a list from an append function with
let to_list append = append []
And since for any list l, I have to_list ## to_append l = l, this means that the to_append is one-to-one: it does not lose any information.
Moreover concatenating two appends functions is exactly function composition
let append_concat f g l = f (g l)
Since we are not building yet any concrete list, append_concat has a constant cost (we are delaying the time complexity to the moment where we will call the append function).
We can use this better behavior of append_concat to write a linear concat' function that maps a list of lists to an append function:
let concat' l =
List.fold_left
(fun append l -> append_concat append (to_append l))
(to_append [] (* aka Fun.id *))
l
Note that this concat' is not yet building a list, it is building a closure which records the list of append functions to call later.
Building concat from concat' is then a matter of transforming back my append function to a list:
let concat l = to_list (concat' l)
And it is the call of to_list which will have a time complexity equal to the size of the final list.
To check that we got the right complexity, we can test that flattening the following list
let test =
List.init 1_000_000
(fun i ->
List.init 4 (fun k -> k + 4 * i)
)
(* this is [[0;1;2;3]; [4;5;6;7]; ... [...; 3_999_999]] *)
with
let flattened = concat test
is nearly instant.

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- Error when evaluating function (This expression has type 'a * 'b but an expression was expected of type ('a * 'b) list#)

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.

F# filtering sublist

Here is an input list: [[10;2;10]; [10;50;10]; [10;1;10]].
How would I filter the second element of each sub-list?
Below is my code and when I output the result I get [[10;50;10]] but what I want is [2;50;1]. Is there anyway to fix my code? I am really trying to understand F#. Thanks for the help in advance.
let sub =
let input = [[10;2;10]; [10;50;10]; [10;1;10]]
let findIndex input elem = input |> List.findIndex ((=) elem)
let q = input |> List.filter(fun elem -> findIndex input elem = 1)
printfn "%A" q
The following will get the expected result:
let second (x:List<int>) = x.[1]
let q = List.map second input
List.map is a higher order function that makes a new list by applying a function (the first argument, here the function second that returns the second element of a list) to a list (here input):
[ [10;2;10]; [10;50;10]; [10;1;10] ]
| | |
second second second <--- mapping function
| | |
V V V
[ 2 ; 50 ; 1 ]
Use List.map, not List.filter
List.filter keeps/removes items from an input list based on the function you give it, e.g. List.filter (fun x -> x % 2 = 0) myList would keep only the even numbers in myList. You can get an idea of this functionality based on its type signature, which is val filter: ('a -> bool) -> 'a list -> 'a list, meaning it takes a function (that takes an 'a and returns a boolean: ('a -> bool)), then takes a list, and returns a list of the same type.
List.map, on the other hand, transforms each element of a list into whatever you want, based on a function you give it. In your case you would use it like so:
let input = [[10;2;10]; [10;50;10]; [10;1;10]]
let result = input |> List.map (fun numbers -> numbers.[1])
printfn "%A" result
The signature of List.map is val map: ('a -> 'b) -> 'a list -> 'b list, meaning it takes a function that maps 'as to 'bs (in your case, this would map int lists to ints), takes a list of the first thing, and returns a list of the second thing.
Use List.map and List.tryIndex
Note that if any of the sub-lists are too short, the program will crash. If this is a concern, you can use a safe version of myList.[i]; namely List.tryIndex, which returns None if the item was not found. Try this out:
// Note the last sublist
let input = [[10;2;10]; [10;50;10]; [10;1;10]; [-1]]
let result : int option list = input |> List.map (fun numbers -> List.tryIndex 1 numbers)
printfn "%A" result
// This prints:
// [Some 2; Some 50; Some 1; None]

Streams (aka "lazy lists") and tail recursion

This question uses the following "lazy list" (aka "stream") type:
type 'a lazylist = Cons of 'a * (unit -> 'a lazylist)
My question is: how to define a tail-recursive function lcycle that takes a non-empty (and non-lazy) list l as argument, and returns the lazylist corresponding to repeatedly cycling over the elements l. For example:
# ltake (lcycle [1; 2; 3]) 10;;
- : int list = [1; 2; 3; 1; 2; 3; 1; 2; 3; 1]
(ltake is a lazy analogue of List::take; I give one implementation at the end of this post.)
I have implemented several non-tail-recursive versions of lcycles, such as:
let lcycle l =
let rec inner l' =
match l' with
| [] -> raise (Invalid_argument "lcycle: empty list")
| [h] -> Cons (h, fun () -> inner l)
| h::t -> Cons (h, fun () -> inner t)
in inner l
...but I have not managed to write a tail-recursive one.
Basically, I'm running into the problem that lazy evaluation is implemented by constructs of the form
Cons (a, fun () -> <lazylist>)
This means that all my recursive calls happen within such a construct, which is incompatible with tail recursion.
Assuming the lazylist type as defined above, is it possible to define a tail-recursive lcycle? Or is this inherently impossible with OCaml?
EDIT: My motivation here is not to "fix" my implementation of lcycle by making it tail-recursive, but rather to find out whether it is even possible to implement a tail recursive version of lcycle, given the definition of lazylist above. Therefore, pointing out that my lcycle is fine misses what I'm trying to get at. I'm sorry I did not make this point sufficiently clear in my original post.
This implementation of ltake, as well as the definition of the lazylist type above, comes from here:
let rec ltake (Cons (h, tf)) n =
match n with
0 -> []
| _ -> h :: ltake (tf ()) (n - 1)
I don't see much of a problem with this definition. The call to inner is within a function which won't be invoked until lcycle has returned. Thus there is no stack safety issue.
Here's an alternative which moves the empty list test out of the lazy loop:
let lcycle = function
| [] -> invalid_arg "lcycle: empty"
| x::xs ->
let rec first = Cons (x, fun () -> inner xs)
and inner = function
| [] -> first
| y::ys -> Cons (y, fun () -> inner ys) in
first
The problem is that you're trying to solve a problem that doesn't exist. of_list function will not take any stack space, and this is why lazy lists are so great. Let me try to explain the process. When you apply of_list function to a non empty list, it creates a Cons of the head of the list and a closure, that captures a reference to the tail of the list. Afterwards it momentary returns. Nothing more. So it takes only few words of memory, and none of them uses stack. One word contains x value, another contains a closure, that captures only a pointer to the xs.
So then, you deconstruct this pair, you got the value x that you can use right now, and function next, that is indeed the closure that, when invoked, will be applied to a list and if it is nonempty, will return another Cons. Note, that previous cons will be already destroyed to junk, so new memory won't be used.
If you do not believe, you can construct an of_list function that will never terminate (i.e., will cycle over the list), and print it with a iter function. It will run for ever, without taking any memory.
type 'a lazylist = Cons of 'a * (unit -> 'a lazylist)
let of_list lst =
let rec loop = function
| [] -> loop lst
| x :: xs -> Cons (x, fun () -> loop xs) in
loop lst
let rec iter (Cons (a, next)) f =
f a;
iter (next ()) f