Explain efficient list reversal recursively - ocaml

(* val rev : ’a list -> ’a list -> ’a list *)
let rec rev l r =
match l with
[] -> r
| (h::t) -> rev t (h::r)
Could some one please tell me what happens here recursively?
Also, why are two arguments l and r used in the code?
Let's say I want to reverse [1;2;3] how does the function reverse is to 3,2,1?
rev [1;2;3] []

What's with the r
Going into detail, let's start with a function without r (accumulator):
let rec rev l =
match l with
[] -> l
| h :: t -> rev t # [h]
What is inefficient here is not just because it's not tail-recursive (which I won't cover in detail; see the link below), but also because you have to append an element [h] to the end of every reversed sublist on every call. In Ocaml, appending to a list is inefficient compared to prepending to it, because a list is a just a singly-linked list, which you only have access to the head's pointer.
Prepending a new element to the head of the list requires only a newly created element to create a pointer to the previous head element and returning a newly created list with that new element as the head. This is only an O(1) operation.
Appending an element to the list, however, incurs an O(N) complexity because you have to traverse to the end of the list before creating a new pointer for the last element to point to the new element. If you have a list of length N where N is a huge number, O(N) is pretty bad.
With an accumulator (r), you are "accumulating" or modifying a state and passing into the next function call. This is the basis of tail-recursion but also avoid the above pitfall. To see what it really does, see the pseudocode below.
What the recursive function does
Here is a visual representation of what happens as the recursive operation goes on (first argument being l and second being r).
(* pseudocode *)
(* while List.length l <> 0 *)
rev [1; 2; 3; 4] []
rev [2; 3; 4] (1 :: [])
rev [3; 4] (2 :: [1])
rev [4] (3 :: [2; 1])
rev [] (4 :: [3; 2; 1])
(* List.length l = 0 *)
return [4; 3; 2; 1]
In practice, you might want to create an inner "helper" function that takes care of the recursive heavy-lifting and leave the outer function simply as a user-friendly, single-arity API.
let rev l =
let rec helper l' r =
match l' with
[] -> r
| (h::t) -> helper t (h::r)
in helper l []
this article on recursion I wrote might help you understand tail-recursion better.

This function is recursive because there is a call of rev inside itself. r parameter is here so called accumulator - thanks to it this function is tail recursive.
How does it work in details?
You call rev [1;2;3] [], so l=[1;2;3] and r=[]. L is matched with h::t - that means head and tail of the list. h=1, t=[2;3].
Last call in the body of rev function is rev [2;3] [1]
In the next call argument l is matched as previous, so rev is called with [3] [2;1]
Last recursive call is rev [] [3;2;1]. L is matched with [] and r (=[3;2;1]) is returned.
Note that you can hide accumulator in the following way:
let rev l =
let rec rev l r = match l with
[] -> r
| (h::t) -> rev t (h::r)
in
rev l []
Then you can use this function passing only one argument rev [1;2;3].

Related

What's wrong with my attempt to add 1 to every element in my list in Ocaml?

I don't understand the error message I'm getting or what's wrong with what I'm trying to do
I just want to use List.fold_left to apply my add1 function to this list [1,2,3]
My add1 function should just add 1 to each element, so I would get [2, 3, 4]
My main goal in doing this exercise is just to experiment with List.fold_left. I don't actually care about adding 1, I just choose that function because it seemed easy to write (I'm an ocaml beginner).
My ultimate goal is actually to populate the keys of a empty StringMap using List.fold_left and a function already written elsewhere, so if anyone has insight on that it would also be appreciated
Here's the 1st try (which I tried twice)
let rec add1 = function
| [] -> []
| h::t -> (h+1)::(add1 t) in List.fold_left add1 [1, 2, 3];;
Here's the 2nd try
let a(b) =
let rec add1 = function
| [] -> []
| h::t -> (h+1)::(add1 t)
in
let c = List.fold_left add1 b
in a [1,2,3];;
I think you should start with:
let add x = x + 1
And then build a function that applies a function to a list via List.fold_left:
let apply_f_to_list_elements fn lst = (*use List.fold_left here*)
Are you sure you want List.fold_left and not List.map?
It may help you to see how fold_left can be implemented.
let rec fold_left f init lst =
match lst with
| [] -> init
| x::xs -> fold_left f (f init x) xs
So consider what's happening when something like a sum function works, when implemented in term of fold_left.
let sum lst =
fold_left (+) 0 lst
If we evaluate sum [1; 2; 3; 4]:
sum [1; 2; 3; 4]
fold_left (+) 0 [1; 2; 3; 4]
fold_left (+) (0 + 1) [2; 3; 4]
fold_left (+) (1 + 2) [3; 4]
fold_left (+) (3 + 3) [4]
fold_left (+) (6 + 4) []
10
We can defined map in terms of fold_left:
let map f lst =
let f' init x = f x :: init in
fold_left f' [] lst
Let's evaluate map (fun x -> x + 1) [5; 2; 6]:
map (fun x -> x + 1) [5; 2; 6]
fold_left f' [] [5; 2; 6]
fold_left f' (5 + 1 :: []) [2; 6]
fold_left f' (2 + 1 :: [6]) [6]
fold_left f' (6 + 1 :: [3; 6]) []
[7; 3; 6]
Now, because of the way we destructure and create lists, the result is backwards. we can overcome this with fold_left by reversing the resulting list.
let map f lst =
let f' init x = f x :: init in
let lst' = fold_left f' [] lst in
List.rev lst'
Or with the |> operator:
let map f lst =
let f' init x = f x :: init in
fold_left f' [] lst |> List.rev
Taking this to the next level
At each iteration, fold_left transforms the first element in a list and an accumulator, into the accumulator for the next iteration. If you want to apply this concept to your StringMap module, consider StringMap.empty which generates an empty StringMap.t, and StringMap.add which take a key, an associated value, and an existing map, and returns a new map with that added mapping.
You can readily use fold_left to take an initially empty map and build it into a complete map step by step. The only question remaining will be what value you choose to associate with each string in your list.
As you seems to confuse map and fold_left I think this quote could help you to understand the difference:
Imagine you have a big dinner with numerous people. You are serving the dish: you go through all the people and replace their empty plates with plates containing food. This is a map operation: the number of plate on the table didn't change, but for each plate, you have done the same action (changing the content of the plate).
Once everything is done, you collect all the dirty plates: This is a fold operation, at the end, there are no more plates on the table, but you have done something for each plates (stacking them) and return the file result (a stack of dirty plates).
In both case, an action is applied systmatically. The difference is that Map preserves the current "structure" (the plates on the table) while Fold removes the structure, and build something else."

I have difficulties with two problems with the langage OCaml

Important: I am only allowed to use List.head, List.tail and List.length
No List.map List.rev ...........etc
Only List.hd, List.tl and List.length
How to duplicate the elements of a list in a list of lists only if the length of the list is odd
Here is the code I tried:
let rec listes_paires x =
if x=[] then []
else [List.hd (List.hd x)]
# (List.tl (List.hd x))
# listes_paires (List.tl x);;
(* editor's note: I don't know where this line is supposed to go*)
if List.length mod 2 = 1 then []
For exemple:
lists_odd [[]; [1];[1;2];[1;2;3];[];[5;4;3;2;1]];;
returns
[[]; [1; 1]; [1; 2]; [1; 2; 3; 1; 2; 3]; []; [5; 4; 3; 2; 1; 5; 4; 3; 2; 1]]
Any help would be very appreciated
thank you all
It looks like that your exercise is about writing recursive functions on lists so that you can learn how to write functions like List.length, List.filter, and so on.
Start with the most simple recursive function, the one that computes the length to the list. Recall, that you can pattern match on the input list structure and make decisions on it, e.g.,
let rec length xs = match xs with
| [] -> 0 (* the empty list has size zero *)
| hd :: tl ->
(* here you can call `length` and it will return you
the length of the list hing how you can use it to
compute the length of the list that is made of `tl`
prepended with `hd` *)
???
The trick is to first write the simple cases and then write the complex cases assuming that your recursive function already works. Don't overthink it and don't try to compute how recursion will work in your head. It will make it hurt :) Just write correctly the base cases (the simple cases) and make sure that you call your function recursively and correctly combine the results while assuming that it works correctly. It is called the induction principle and it works, believe me :)
The above length function was easy as it was producing an integer as output and it was very easy to build it, e.g., you can use + to build a new integer from other integers, something that we have learned very early in our lives so it doesn't surprise us. But what if we want to build something more complex (in fact it is not more complex but just less common to us), e.g., a list data structure? Well, it is the same, we can just use :: instead of + to add things to our result.
So, lets try writing the filter function that will recurse over the input list and build a new list from the elements that satisfy the given predicate,
let rec filter xs keep = match xs with
| [] -> (* the simple case - no elements nothing to filter *)
[]
| x :: xs ->
(* we call filter and it returns the correctly filtered list *)
let filtered = filter xs keep in
(* now we need to decide what to do with `x` *)
if keep x then (* how to build a list from `x` and `filtered`?*)
else filtered (* keep filtering *)
The next trick to learn with recursive functions is how to employ helper functions that add an extra state (also called an accumulator). For example, the rev function, which reverses a list, is much better to define with an extra accumulator. Yes, we can easily define it without it,
let rec rev xs = match xs with
| [] -> []
| x :: xs -> rev xs # [x]
But this is an extremely bad idea as # operator will have to go to the end of the first list and build a completely new list on the road to add only one element. That is our rev implementation will have quadratic performance, i.e., for a list of n elements it will build n list each having n elements in it, only to drop most of them. So a more efficient implementation will employ a helper function that will have an extra parameter, an accumulator,
let rev xs =
(* we will pump elements from xs to ys *)
let rec loop xs ys = match xs with
| [] -> ys (* nothing more to pump *)
| x :: xs ->
let ys = (* push y to ys *) in
(* continue pumping *) in
loop xs []
This trick will also help you in implementing your tasks, as you need to filter by the position of the element. That means that your recursive function needs an extra state that counts the position (increments by one on each recursive step through the list elements). So you will need a helper function with an extra parameter for that counter.

How to use fold on an elaborate function in ocaml

As the title suggests, I want to use fold. If I understand correctly, it it used to apply a function to every item in a list. That's what I want to do with my function, but I don't know how to format it.
Here is the function I want to use with fold :
let pairing list =
let rec aux counter length paired list = match list with
| [] -> paired
| [head] -> paired
| head :: head' :: tail -> if counter = length then aux (counter-1) length ((head, head) :: paired) (head :: head' :: tail) else aux counter length ((head, head') :: paired) (head' :: tail)
in List.rev(aux (List.length(listheads list)) (List.length(listheads list)) [] (listheads list));;
What it does is it returns a list of all the items in the list paired together.
For example, if my list is [3;4;2], it should return
[(3,3); (3,4); (3,2); (4,3); (4,4); (4,2); (2,3); (2,4); (2,2)]
What it returns at the moment is only [(3,3); (3,4); (3,2)], because the function only applies to the first item of the list.
Here are all the helper functions :
let rec member list x = match list with
| [] -> false
| head :: tail -> head = x || member tail x
let head_list list =
let rec aux l1 list = match list with
| [] -> l1
| (x,y) :: tail -> aux (x :: l1) tail
in List.rev (aux [] list);;
let head'_list list =
let rec aux l2 list = match list with
| [] -> l2
| (x,y) :: tail -> aux (y :: l2) tail
in List.rev (aux [] list);;
let listheads list =
let rec aux returnlist l1 l2 = match l1 with
| [] -> returnlist
| head :: tail -> if member l2 head = true && member returnlist head = false then aux (head :: returnlist) tail l2 else aux returnlist tail l2
in List.rev(aux [] (head_list list) (head'_list list));;
What listheads does is it will take my original list (say [(3,4); (4,2); (2,3); (4,7); (9,4)]), use head_list and head'_list in order to determine which integers are both in head and head' position in the tuple, and put them in the list (in the case I gave, [3;4;2]).
I know that fold takes a function, an empty list and a list as arguments, but I don't know how to use pairing with fold.
Your code need to make a double pass on the list
let pairing l =
let second_pass x acc y = ...... in
let first_pass acc el = ....... in
List.fold_left first_pass [] l |> List.rev
The first pass function should call the second pass function, and the second pass function will create the pair element. Free to you for completing the code of the two functions.
Here the result I have :
utop # pairing [3 ; 4 ; 2];;
- : (int * int) list =
[(3, 3); (3, 4); (3, 2); (4, 3); (4, 4); (4, 2); (2, 3); (2, 4); (2, 2)]
It's very difficult to answer your question because there's no clean place to add a fold to get the result you want.
It might be more fruitful just to debug your code. It seems to me you're using your counter backwards. Its initial value is the length of the list and it is decremented for each recursive call. But your test for termination tests against the length of the list. It seems to me you should be testing against 0 (or possibly 1).
If you have a function f that does something interesting to a value, and you have a list of the values, you can use List.map to get a list of the values of f applied to each element of the list. You don't need a fold for that.
The purpose of a fold is to compute thing other than just a list of the function values. For examle, if each call to f makes a list of values, you could use a fold to keep concatenating these lists into a longer list.
Let's say f makes a value x into a list [x; x]. Then you can create a (reversed) doubled list something like this:
let f x = [x; x]
let double l =
let aux sofar x = f x # sofar in
List.fold_left aux [] l
# double [1;2;3];;
- : int list = [3; 3; 2; 2; 1; 1]
You could possibly follow this pattern if you can come up with a function like f that transforms a value into a list. If you define f inside your outer function it will have access to the initial list.

Error in code to flatten a list in Ocaml

Hello All I am trying to flatten a list in Ocaml. I am a newbie so please pardon me if my mistake is dumb
So for example, if input is [[1];[2;3];[4]] I should end up with [1;2;3;4].
The idea I am trying to use is as follows
Iterate through the list from the right (Using fold_right) with accumaltor = []
The pseudo code is as follows
func flatten(list, accumalator)
For each item from right to left in list
If Item is a scalar then n :: accumalator
Else fi Item is a list of form head :: tail then
head :: flatten (tail, accumalator).
I think that theoretically the algorithm is correct, but please let me know if you disagree.
Now to my OCaml code to implement this algorithm
let rec flatten acc x =
match x with
n -> n :: acc
| [x] -> x :: acc
| head :: remainder ->
head :: ( my_flat acc remainder )
and my_flat = List.fold_right flatten
;;
my_flat [] [[1];[2;3];[4]]
The Error I get is the following
Error: This expression has type 'a but an expression was expected of type
'a list
The error occurs on the line that reads head :: ( my_flat acc remainder ) in the last pattern in the match statement
Any help is appreciated.
In OCaml, all the elements of a list must be the same type. Thus the value [1; [2; 3]; 4] is invalid all by itself. It contains two elements that are of type int and one element of type int list. In essence, your statement of the problem to be solved is impossible.
$ ocaml312
Objective Caml version 3.12.0
# [1; [2; 3]; 4];;
Characters 4-10:
[1; [2; 3]; 4];;
^^^^^^
Error: This expression has type 'a list
but an expression was expected of type int
This sounds like a homework problem, so I'll just say that restricting yourself to lists that are valid in OCaml may make it easier to solve.
Edit
OK, the problem can now be solved!
The essence of the reported type error is something like this. You have your accumulated result acc (of type int list in the example). You want to add the list x (also of type int list) to it. You've broken x into head (an int) and remainder (an int list). As you can see, remainder is not a suitable argument for your my_flat function. It wants an int list list, i.e., a list of lists of ints. In fact, your recursive call should almost certainly go to flatten and not to my_flat.
Another problem I see: the arguments of List.fold_right are: a function, a list, and a starting value. In your test call to my_flat, you're supplying the last two in the other order. The empty list [] is your starting value.
I hope this is enough to get you going. Since you're just starting out with OCaml there will probably be another problem or two before it works.
Edit 2
Here are a couple more comments, which might be spoilers if you're still working on your own solution....
A tidier version of your function my_flat is in the OCaml standard library under the name List.flatten. It's interesting to look at the implementation:
let rec flatten = function
[] -> []
| l::r -> l # flatten r
I'd call this a very elegant solution, but unfortunately it's not tail recursive. So it will consume some (linear) amount of stack space, and might even crash for a very long list.
Here's one based on the same idea, using the standard FP accumulator trick to get tail recursive behavior (as noted by Thomas):
let flatten2 ll =
let rec go acc = function
| [] -> List.rev acc
| l :: r -> go (List.rev_append l acc) r
in
go [] ll
As is often the case, the tail recursive version accumulates the result in reverse order, and reverses it at the end.
You can start by writing directly your algorithm, by decomposing the base cases of your input value, ie. the input list is either empty, or the head of the input list is empty, or the head of the input list has a head and a tail:
let rec flatten = function
| [] -> []
| [] :: t -> flatten t
| (x::y) :: t -> x :: (flatten (y::t))
You can then optimize the function, because this code is not tail-recursive and thus will crash when lists become too big. So you can rewrite this by using the usual technique:
let flatten list =
let rec aux accu = function
| [] -> accu
| [] :: t -> aux accu t
| (x::y) :: t -> aux (x::accu) (y::t) in
List.rev (aux [] list)
So my advice is: start by decomposing your problem based on the input types, and then later use accumulators to optimize your code.
I like this one, where the auxiliary function takes the accumulator, the first element of the list of lists, and the rest of the list of lists, it is clearer for me :
let flatten list =
let rec aux acc list1 list2 =
match list1 with
| x :: tail -> aux (x :: acc) tail list2
| [] ->
match list2 with
| [] -> List.rev acc
| x :: tail -> aux acc x tail
in
aux [] [] list
Thanks for all your help
Here is the code I used to solve this problem
let flatten list =
let rec flatten_each acc x =
match x with
[] -> acc
| head :: remainder -> head :: ( flatten_each acc remainder )
in
List.fold_right flatten_each ( List.rev list ) []
;;
Edit: as pointed out by Thomas this solution is not tail recursive. Tail recursive version is below
let flatten list =
let rec flatten_each acc x =
match x with
[] -> acc
| head :: remainder -> (flatten_each (acc # [head]) remainder )
in
List.fold_right flatten_each list []
;;

Combine Lists with Same Heads in a 2D List (OCaml)

I'm working with a list of lists in OCaml, and I'm trying to write a function that combines all of the lists that share the same head. This is what I have so far, and I make use of the List.hd built-in function, but not surprisingly, I'm getting the failure "hd" error:
let rec combineSameHead list nlist = match list with
| [] -> []#nlist
| h::t -> if List.hd h = List.hd (List.hd t)
then combineSameHead t nlist#uniq(h#(List.hd t))
else combineSameHead t nlist#h;;
So for example, if I have this list:
[[Sentence; Quiet]; [Sentence; Grunt]; [Sentence; Shout]]
I want to combine it into:
[[Sentence; Quiet; Grunt; Shout]]
The function uniq I wrote just removes all duplicates within a list. Please let me know how I would go about completing this. Thanks in advance!
For one thing, I generally avoid functions like List.hd, as pattern maching is usually clearer and less error-prone. In this case, your if can be replaced with guarded patterns (a when clause after the pattern). I think what is happening to cause your error is that your code fails when t is []; guarded patterns help avoid this by making the cases more explicit. So, you can do (x::xs)::(y::ys)::t when x = y as a clause in your match expression to check that the heads of the first two elements of the list are the same. It's not uncommon in OCaml to have several successive patterns which are identical except for guards.
Further things: you don't need []#nlist - it's the same as just writing nlist.
Also, it looks like your nlist#h and similar expressions are trying to concatenate lists before passing them to the recursive call; in OCaml, however, function application binds more tightly than any operator, so it actually appends the result of the recursive call to h.
I don't, off-hand, have a correct version of the function. But I would start by writing it with guarded patterns, and then see how far that gets you in working it out.
Your intended operation has a simple recursive description: recursively process the tail of your list, then perform an "insert" operation with the head which looks for a list that begins with the same head and, if found, inserts all elements but the head, and otherwise appends it at the end. You can then reverse the result to get your intended list of list.
In OCaml, this algorithm would look like this:
let process list =
let rec insert (head,tail) = function
| [] -> head :: tail
| h :: t ->
match h with
| hh :: tt when hh = head -> (hh :: (tail # t)) :: t
| _ -> h :: insert (head,tail) t
in
let rec aux = function
| [] -> []
| [] :: t -> aux t
| (head :: tail) :: t -> insert (head,tail) (aux t)
in
List.rev (aux list)
Consider using a Map or a hash table to keep track of the heads and the elements found for each head. The nlist auxiliary list isn't very helpful if lists with the same heads aren't adjacent, as in this example:
# combineSameHead [["A"; "a0"; "a1"]; ["B"; "b0"]; ["A"; "a2"]]
- : list (list string) = [["A"; "a0"; "a1"; "a2"]; ["B"; "b0"]]
I probably would have done something along the lines of what antonakos suggested. It would totally avoid the O(n) cost of searching in a list. You may also find that using a StringSet.t StringMap.t be easier on further processing. Of course, readability is paramount, and I still find this hold under that criteria.
module OrderedString =
struct
type t = string
let compare = Pervasives.compare
end
module StringMap = Map.Make (OrderedString)
module StringSet = Set.Make (OrderedString)
let merge_same_heads lsts =
let add_single map = function
| hd::tl when StringMap.mem hd map ->
let set = StringMap.find hd map in
let set = List.fold_right StringSet.add tl set in
StringMap.add hd set map
| hd::tl ->
let set = List.fold_right StringSet.add tl StringSet.empty in
StringMap.add hd set map
| [] ->
map
in
let map = List.fold_left add_single StringMap.empty lsts in
StringMap.fold (fun k v acc-> (k::(StringSet.elements v))::acc) map []
You can do a lot just using the standard library:
(* compares the head of a list to a supplied value. Used to partition a lists of lists *)
let partPred x = function h::_ -> h = x
| _ -> false
let rec combineHeads = function [] -> []
| []::t -> combineHeads t (* skip empty lists *)
| (hh::_ as h)::t -> let r, l = List.partition (partPred hh) t in (* split into lists with the same head as the first, and lists with different heads *)
(List.fold_left (fun x y -> x # (List.tl y)) h r)::(combineHeads l) (* combine all the lists with the same head, then recurse on the remaining lists *)
combineHeads [[1;2;3];[1;4;5;];[2;3;4];[1];[1;5;7];[2;5];[3;4;6]];;
- : int list list = [[1; 2; 3; 4; 5; 5; 7]; [2; 3; 4; 5]; [3; 4; 6]]
This won't be fast (partition, fold_left and concat are all O(n)) however.