在 OCaml 中将 `('a list * b' list) list` 扁平化为 `'a list* 'b list` 的函数

Function to flatten `('a list * b' list) list` to `'a list* 'b list` in OCaml

我需要 OCaml 中的一个函数,它将采用一种类型 ('a list * b' list) list 创造它
'a list * b' list。我尝试使用内置函数 List.flatten 和 List.concat 但它们不起作用,它们需要一种类型 'c list list。有人可以帮助我吗?

您可以像这样使用函数 fold_left 来完成它:

您从两个用作累加器的空列表开始。对于输入列表中的每个 sub-lists,您将元素添加到相应的累加器中(第一个 sub-list 的元素在第一个累加器中,第二个 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>
# 

以下应该有效:

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)

这里,split2会把一个('a list * 'b list) list变成一个('a list list * 'b list list)fstsndreturn的第一个和第二个组成部分一对)和 flatten2' 将分别展平这两个组件。 flatten2 最终会完成您的要求。你也可以把它打包成一个函数,但我觉得这样更容易理解。

注意List.mapList.flatten都不是tail-recursive;如果你需要 tail-recursive 版本,还有其他库有它们,或者你可以使用 rev_xxx 函数从标准库构建它们或从头开始编写它们。

您必须使用函数 List.splitList.flatten:

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

首先,split 函数将生成 'a list list 和一个 'b list list,然后您只需 flatten 它们。

不幸的是,没有元组映射,您需要分解 - 例如使用拆分和展平:

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

这就是它在命令行上的样子:

utop # splcat [([1;2],["a"]); ([3],["uvw";"xyz"]) ] ;;
- : int list * bytes list = ([1; 2; 3], ["a"; "uvw"; "xyz"])