I want to essentially transpose a matrix in OCaml (without using recursion or any sort of looping)
For example, if I have the following matrix: [[1;2];[3;4]]
Assuming your list of lists is rectangular, this Standard ML code translates to OCaml as such:
let rec transpose xss =
match xss with
| [] -> []
| []::_ -> []
| _ -> List.map List.hd xss :: transpose (List.map List.tl xss)
It extracts the first column (List.map List.hd xss
) and recursively combines it with the extraction of the remaining columns, after having removed the already extracted column (List.map List.tl xss
).
The explicit recursion that still remains in this function cannot easily be replaced by mapping / folding, since those would address one row at a time, where the recursion scheme above addresses (a part of) all rows at once. You might have more luck with unfolding / anamorphism:
let rec unfold f a =
match f a with
| Some (b, a') -> b :: unfold f a'
| None -> []
val unfold : ('a -> ('b * 'a) option) -> 'a -> 'b list = <fun>
where 'a
could be the gradual reduction of your input row matrix, and 'b
the matrix columns:
let transpose =
unfold (function
| [] -> None
| []::_ -> None
| m -> Some (List.map List.hd m, List.map List.tl m))
I question whether your separate
function separates the matrix into columns. Here's what I see:
# let separate li = List.map (fun x -> [x]) li;;
val separate : 'a list -> 'a list list = <fun>
# List.map separate [[1;2];[3;4]];;
- : int list list list = [[[1]; [2]]; [[3]; [4]]]
I don't see columns, I just see that you've put each matrix element into its own list.
To get the first column you could try this:
# List.map List.hd [[1;2]; [3;4]];;
- : int list = [1; 3]
If you use List.tl
rather than List.hd
you get the remainders of the rows. Maybe you can use a fold to apply this repeatedly and collect up the results.