Home > database >  Reversing tuples inside a list with fold_left in Ocaml
Reversing tuples inside a list with fold_left in Ocaml

Time:06-20

Let lst be a List with tuples which I want to reverse each (The order of the tuples needs to be the same). For example:

[(a,b);(c,d)] -> [(b,a);(d,c)] 

I know that it can be done with map:

List.map (fun (a,b) -> (b,a)) [(1,2);(3,4)];;
- : (int * int) list = [(2, 1); (4, 3)]

But I´m looking for a way to achieve it with List.fold_left. My approach is to match the list with [] as a accumulator to concatenate every reversed tuple together, but I keep getting type-Errors:

List.fold_left (fun (a,b) -> (b,a)) [] lst;;

CodePudding user response:

List.fold_left takes three arguments:

  • A function of type 'a -> 'b -> 'a
  • An accumulator of type 'a
  • A list of type 'b list

Your function (fun (a,b) -> (b,a)) is missing an argument, the accumulator, on which you want to concatenate the reversed pairs

(fun acc (a,b) -> (b,a) :: acc)

CodePudding user response:

Both the answer by @Lhooq and @rithvik are mostly spot-on, but will reverse the order of the tuples in the resulting list.

We either need to feed the result to List.rev or use List.fold_right.

utop # List.fold_left (fun acc (a, b) -> (b, a) :: acc) [] [(1, 2); (3, 4)] |> List.rev;;
- : (int * int) list = [(2, 1); (4, 3)]
utop # List.fold_right (fun (a, b) acc -> (b, a) :: acc) [(1, 2); (3, 4)] [];;
- : (int * int) list = [(2, 1); (4, 3)]

CodePudding user response:

Using List.map seems like a natural option here, because you could do something like:

List.map (fun (a, b) -> (b, a)) lst

But if you wanted to use List.fold_left then you need to reverse each pair and then cons it to the accumulator list:

List.fold_left (fun acc (a, b) -> (b, a)::acc) [] lst

Since fold_left takes the following function signature: ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a, you need to make sure that your first argument is a function that takes in an accumulator list and an individual list element (in this case a tuple), and then returns a list.

EDIT: @Chris rightly pointed out that with this solution the order of the tuples themselves would also flip. You can fix this by wrapping the function with List.rev, or instead of cons-ing you can append the tuple to the end of the list:

List.fold_left (fun acc (a, b) -> acc@[(b, a)]) [] lst

  • Related