Error in code to flatten a list in Ocaml - 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 []
;;

Related

Appending two lists

So this is one way to append two lists:
let rec append l1 l2 =
match l1 with
| h :: t -> h :: append t l2
| [] -> l2
But I am trying to write a tail-recursive version of append. (solve the problem before calling the recursive function).
This is my code so far, but when I try to add append in the first if statement the code becomes faulty for weird reasons.
let list1 = [1;2;3;4]
let list2 = [5;6;7;8]
let rec append lista listb =
match listb with
| h :: taillist -> if taillist != [] then
begin
lista # [h];
(* I cant put an append recursive call here because it causes error*)
end else
append lista taillist;
| [] -> lista;;
append list1 list2;;
The easiest way to transform a non tail-recursive list algorithm into a tail-recursive one, is to use an accumulator. Consider rewriting your code using a third list, that will accumulate the result. Use cons (i.e., ::) to prepend new elements to the third list, finally you will have a result of concatenation. Next, you need just to reverse it with List.rev et voila.
For the sake of completeness, there is a tail-recursive append:
let append l1 l2 =
let rec loop acc l1 l2 =
match l1, l2 with
| [], [] -> List.rev acc
| [], h :: t -> loop (h :: acc) [] t
| h :: t, l -> loop (h :: acc) t l
in
loop [] l1 l2
I would recommend to solve 99 problems to learn this idiom.
A couple of comments on your code:
It seems like cheating to define a list append function using #, since this is already a function that appends two lists :-)
Your code is written as if OCaml were an imperative language; i.e., you seem to expect the expression lista # [h] to modify the value of lista. But OCaml doesn't work that way. Lists in OCaml are immutable, and lista # [h] just calculates a new value without changing any previous values. You would need to pass this new value in your recursive call.
As #ivg says, the most straightforward way to solve your problem is using an accumulator, with a list reversal at the end. This is a common idiom in a language with immutable lists.
A version using constant stack space, implemented with a couple of standard functions (you'll get a tail-recursive solution after unfolding the definitions):
let append xs ys = List.rev_append (List.rev xs) ys
Incidentally, some OCaml libraries implement the append function in a pretty sophisticated way:
(1) see core_list0.ml in the Core_kernel library: search for "slow_append" and "count_append"
(2) or batList.mlv in the Batteries library.
An alternative tail-recursive solution (F#) leveraging continuations :
let concat x =
let rec concat f = function
| ([], x) -> f x
| (x1::x2, x3) -> concat (fun x4 -> f (x1::x4)) (x2, x3)
concat id x
I think the best way to go about it, like some have said would be to reverse the first list, then recursively add the head to the front of list2, but the top comment with code uses an accumulator, when you can get the same result without it by :: to the second list instead of an accumulator
let reverse list =
let rec reverse_helper acc list =
match list with
| [] -> acc
| h::t -> reverse_helper (h::acc) t in
reverse_helper [] lst;;
let append list1 list2 =
let rec append_helper list1_rev list2 =
match list1_rev with
| [] -> list2
| h :: t -> append_helper t (h::lst2) in
append_helper (reverse lst1) lst2;;
A possible answer to your question could be the following code :
let append list1 list2 =
let rec aux acc list1 list2 = match list1, list2 with
| [], [] -> List.rev(acc)
| head :: tail, [] -> aux (head :: acc) tail []
| [], head :: tail -> aux (head :: acc) [] tail
| head :: tail, head' :: tail' -> aux (head :: acc) tail (head' :: tail')
in aux [] list1 list2;
It's pretty similar to the code given by another one of the commenters on your post, but this one is more exhaustive, as I added a case for if list2 is empty from the beginning and list1 isn't
Here is a simpler solution:
let rec apptr l k =
let ln = List.rev l in
let rec app ln k acc = match ln with
| [] -> acc
| h::t -> app t k (h::acc) in
app ln k k
;;
let rec append (mylist: 'a list) (myotherlist : 'a list ): 'a list =
match mylist with
| [] -> myotherlist
| a :: rest -> a :: append rest myotherlist

SML list summing

I'm very new to SML and I am trying a list exercise. The goal is sum up the previous numbers of a list and create a new list. For example, an input list [1, 4, 6, 9] would return [1, 5, 11, 20].
This is my solution so far, but I think the issue is with how I'm defining the function.
fun rec sum:int list -> int list =
if tl(list) = nil then
hd(list)
else
hd :: sum((hd(tail) + hd(tl(list)))::tl(tl(list)));
Besides that you are using rec as a function name, then you have some minor issues to work on.
The explicit type annotation you have made is treated as an annotation of the function result.
Thus, according to what you have written, then it should return a function and not the expected
list. This is clearly seen from the below example:
- fun rec_ sum : int list -> int list = raise Domain;
val rec_ = fn : 'a -> int list -> int list
Your should be careful of using the head and tail functions, when you don't do any checks on the
number of elements in the list. This could be done with either the length function, or (even
easier and often better) by pattern matching the number of elements.
Your code contains sum as a function call and tail as an variable. The variable tail has never
been defined, and using sum as a function call, makes me believe that you are actually using rec
as a keyword, but don't know what it means.
The keyword rec is used, when defining functions using the val keyword. In this case, rec is
needed to be able to define recursive functions (not a big surprise). In reality, the keyword fun
is syntactic sugar (a derived form) of val rec.
The following 3 are examples of how it could have been made:
The first is a simple, straight forward solution.
fun sumList1 (x::y::xs) = x :: sumList1 (x+y::xs)
| sumList1 xs = xs
This second example, uses a helper function, with an added argument (an accumulator). The list is constructed in the reverse order, to avoid using the slow append (#) operator. Thus we reverse the list before returning it:
fun sumList2 xs =
let
fun sumList' [] acc = rev acc
| sumList' [x] acc = rev (x::acc)
| sumList' (x :: y :: xs) acc = sumList' (y+x :: xs) (x :: acc)
in
sumList' xs []
end
The last example, show how small and easy it can be, if you use the standard list functions. Here the fold left is used, to go through all elements. Again note that the list is constructed in the reverse order, thus it is reversed as the last step:
fun sumList3 [] = []
| sumList3 (x::xs) = rev (foldl (fn (a, b) => hd b + a :: b) [x] xs)
try this -
fun recList ([], index, sum) = []
| recList (li, index, sum) =
if index=0 then
hd li :: recList (tl li, index+1, hd li)
else
sum + hd li :: recList (tl li, index+1, sum + hd li)
fun recSum li = recList (li, 0, 0)
In your case -
recSum([1,4,6,9]) ;
will give
val it = [1,5,11,20] : int list
also don't use rec as fun name -it keyword .

Ocaml list of ints to list of int lists (Opposite of flattening)

With a list of integers such as:
[1;2;3;4;5;6;7;8;9]
How can I create a list of list of ints from the above, with all new lists the same specified length?
For example, I need to go from:
[1;2;3;4;5;6;7;8;9] to [[1;2;3];[4;5;6];[7;8;9]]
with the number to split being 3?
Thanks for your time.
So what you actually want is a function of type
val split : int list -> int -> int list list
that takes a list of integers and a sub-list-size. How about one that is even more general?
val split : 'a list -> int -> 'a list list
Here comes the implementation:
let split xs size =
let (_, r, rs) =
(* fold over the list, keeping track of how many elements are still
missing in the current list (csize), the current list (ys) and
the result list (zss) *)
List.fold_left (fun (csize, ys, zss) elt ->
(* if target size is 0, add the current list to the target list and
start a new empty current list of target-size size *)
if csize = 0 then (size - 1, [elt], zss # [ys])
(* otherwise decrement the target size and append the current element
elt to the current list ys *)
else (csize - 1, ys # [elt], zss))
(* start the accumulator with target-size=size, an empty current list and
an empty target-list *)
(size, [], []) xs
in
(* add the "left-overs" to the back of the target-list *)
rs # [r]
Please let me know if you get extra points for this! ;)
The code you give is a way to remove a given number of elements from the front of a list. One way to proceed might be to leave this function as it is (maybe clean it up a little) and use an outer function to process the whole list. For this to work easily, your function might also want to return the remainder of the list (so the outer function can easily tell what still needs to be segmented).
It seems, though, that you want to solve the problem with a single function. If so, the main thing I see that's missing is an accumulator for the pieces you've already snipped off. And you also can't quit when you reach your count, you have to remember the piece you just snipped off, and then process the rest of the list the same way.
If I were solving this myself, I'd try to generalize the problem so that the recursive call could help out in all cases. Something that might work is to allow the first piece to be shorter than the rest. That way you can write it as a single function, with no accumulators
(just recursive calls).
I would probably do it this way:
let split lst n =
let rec parti n acc xs =
match xs with
| [] -> (List.rev acc, [])
| _::_ when n = 0 -> (List.rev acc, xs)
| x::xs -> parti (pred n) (x::acc) xs
in let rec concat acc = function
| [] -> List.rev acc
| xs -> let (part, rest) = parti n [] xs in concat (part::acc) rest
in concat [] lst
Note that we are being lenient if n doesn't divide List.length lst evenly.
Example:
split [1;2;3;4;5] 2 gives [[1;2];[3;4];[5]]
Final note: the code is very verbose because the OCaml standard lib is very bare bones :/ With a different lib I'm sure this could be made much more concise.
let rec split n xs =
let rec take k xs ys = match k, xs with
| 0, _ -> List.rev ys :: split n xs
| _, [] -> if ys = [] then [] else [ys]
| _, x::xs' -> take (k - 1) xs' (x::ys)
in take n xs []

OCaml - Move last element of list to front

First off, I apologize if this is a confusing or backwards way to go about what I want to accomplish, but I'm new to "OCaml style".
I want to take the last element of a list, and move it to the front of the list, shifting all the elements up one.
For example: have [1;2;3;4;5] -> [5;1;2;3;4]
I understand that lists in OCaml are basically linked list, so I plan to recursively iterate through the list, find the last element, and then have that element's tail/remaining list point to the head of the list.
What I'm mainly confused about is how to break the link from the second last element to the last element. In the example above, I want to have the 5 point to the 1, but the 4 to no longer point to the 5.
How do I accomplish this, and is there a simpler way to look at this that I'm completely missing?
You can't "Break the link" because Ocaml lists are a persistent data-structure. You can't really modify the lists, so you have to produce a new list with the values in the order you want.
let thelist = [1;2;3;4;5] in
let lnewhead = List.hd (List.rev thelist) in
lnewhead :: (List.rev (List.tl (List.rev b)));;
You could also define this in a function:
let flipper = fun thelist ->
(List.hd (List.rev thelist)) :: (List.rev (List.tl (List.rev thelist)));;
val flipper : 'a list -> 'a list = <fun>
# flipper([1;2;3;4;5]);;
- : int list = [5; 1; 2; 3; 4]
Joshua's code can be slightly improved in terms of time complexity by making sure List.rev thelist is computed only once, as in:
let flipper =
fun thelist ->
let r = List.rev thelist in
List.hd r :: List.rev (List.tl r)
A safe implementation is the following:
let rot1 l =
let rec aux acc = function
[] -> []
| [x] -> x :: List.rev acc
| x :: l -> aux (x :: acc) l
in
aux [] l
It is safe in the sense that passing the empty list returns the empty list instead of raising an exception. Note that I strongly discourage the use of List.hd and List.tl because they may fail, with a generic error message.
Also, the recursive call to aux is a tail call (last thing to do before returning). The OCaml compilers will detect this and avoid growing the stack with each function call (and possibly raise an exception or crash). This is something to be aware of when dealing with long lists and recursive functions.
In order to do this operation efficiently, i.e. in O(1) rather than O(length), you cannot use a regular list. You can use the Queue module from the standard library or implementations of doubly-linked lists provided by third parties.
Here is an example using the Queue module:
let rotate_queue q =
if not (Queue.is_empty q) then
let x = Queue.take q in
Queue.add x q
# let q = Queue.create ();;
val q : '_a Queue.t = <abstr>
# Queue.add 1 q;;
- : unit = ()
# Queue.add 2 q;;
- : unit = ()
# Queue.add 3 q;;
- : unit = ()
# Queue.iter print_int q;;
123- : unit = ()
# rotate_queue q;;
- : unit = ()
# Queue.iter print_int q;;
231- : unit = ()
#
The Dllist module of the Batteries library might be what you are looking for. It is an imperative list structure.

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.