1

I need a function in OCaml that will take a type of ('a list * b' list) list and make of it
'a list * b' list. I have tried with the built in functions List.flatten and List.concat but they do not work, they require a type of 'c list list. Can someone help me?

4 Answers4

2

You have to use the functions List.split and List.flatten:

 let my_function l =
   let (fst_list, snd_list) = List.split l in
   List.flatten fst_list, List.flatten snd_list ;;

First the split function will generate and 'a list list and a 'b list list, then you just have to flatten them.

Çağdaş Bozman
  • 2,537
  • 16
  • 21
1

You can do it using the function fold_left like this :

You start with two empty lists working as accumulators. For every sub-lists in your the input list, you add the elements into the respective accumulator (elements of the first sub-list in the first accumulator and same thing for the second sub-list).

# let flatten l =
  let (l1,l2) =
    List.fold_left (fun (l1,l2) (x,y) ->
        (x :: l1, y :: l2)) ([], []) l in
  List.rev (List.flatten l1), List.rev (List.flatten l2);;
        val flatten : ('a list * 'b list) list -> 'a list * 'b list = <fun>
# 
alifirat
  • 2,899
  • 1
  • 17
  • 33
  • This is ok, but I need something to do `('a list * 'b list) list -> 'a list * 'b list` and not `('a * 'b) list -> 'a list * 'b list` – measuretheory Jan 20 '16 at 22:55
  • But it is still not what I need :( The order is not so important, what is important is what the input in the function is. Your gives `('a * 'b) list -> 'a list * 'b list` and I need `('a list * 'b list) list -> 'a list * 'b list` – measuretheory Jan 20 '16 at 23:00
  • Look my answer please, the function have the excepted type. – alifirat Jan 20 '16 at 23:02
  • You seem to understand OCaml really good, this function I needed to finish another exercise that I posted up here, but even with this it does not work, if you have time it would be great if you could take a look at it http://stackoverflow.com/questions/34858154/ocaml-function-with-data-type-tree/34878701#34878701 I am working on it for days now and I still do not have an answer :/ – measuretheory Jan 20 '16 at 23:19
1

Unfortunately there is no map for tuples and you need to decompose - e.g. using using split and flatten:

let splcat x = match List.split x with | (a,b) -> (List.flatten a, List.flatten b) ;;

That's how it looks on the commandline:

utop # splcat [([1;2],["a"]); ([3],["uvw";"xyz"]) ] ;;
- : int list * bytes list = ([1; 2; 3], ["a"; "uvw"; "xyz"])     
lambda.xy.x
  • 4,918
  • 24
  • 35
0

The following should work:

let split2 l = (List.map fst l, List.map snd l)
let flatten2' (l1, l2) = (List.flatten l1, List.flatten l2)
let flatten2 l = flatten2' (split2 l)

Here, split2 will turn a ('a list * 'b list) list into a ('a list list * 'b list list) (fst and snd return the first and second component of a pair, respectively) and flatten2' will individually flatten the two components. And flatten2 will finally do what you require. You can also pack this into a single function, but I think this is easier to understand.

Note that neither List.map nor List.flatten is tail-recursive; if you need tail-recursive versions, there are other libraries that have them, or you can build them from the standard library using rev_xxx functions or write them from scratch.

Reimer Behrends
  • 8,600
  • 15
  • 19