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 typeintand one element of typeint list. In essence, your statement of the problem to be solved is impossible.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 typeint listin the example). You want to add the listx(also of typeint list) to it. You’ve brokenxintohead(anint) andremainder(anint list). As you can see,remainderis not a suitable argument for yourmy_flatfunction. It wants anint list list, i.e., a list of lists of ints. In fact, your recursive call should almost certainly go toflattenand not tomy_flat.Another problem I see: the arguments of
List.fold_rightare: a function, a list, and a starting value. In your test call tomy_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_flatis in the OCaml standard library under the nameList.flatten. It’s interesting to look at the implementation: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):
As is often the case, the tail recursive version accumulates the result in reverse order, and reverses it at the end.