在OCaml中将`('列表* b'列表)列表'展平为''列表*'b列表`的功能

时间:2016-01-20 22:44:57

标签: list functional-programming ocaml

我需要在OCaml中使用一种类型的函数     ('a list * b' list) list并制作它 'a list * b' list。我已尝试使用内置函数List.flatten和List.concat,但它们不起作用,它们需要'c list list类型。有人能帮助我吗?

4 个答案:

答案 0 :(得分:2)

您必须使用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

答案 1 :(得分:1)

您可以使用fold_left函数执行此操作:

您从两个用作累加器的空列表开始。对于输入列表中的每个子列表,将元素添加到相应的累加器中(第一个累加器中第一个子列表的元素和第二个子列表中的相同内容)。

# 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>
# 

答案 2 :(得分:1)

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

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"])     

答案 3 :(得分:0)

以下内容应该有效:

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)fstsnd分别返回一对的第一个和第二个组成部分) flatten2'将单独展平这两个组件。 flatten2最终将满足您的需求。您也可以将其打包成一个函数,但我认为这更容易理解。

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