我需要在OCaml中使用一种类型的函数
('a list * b' list) list
并制作它
'a list * b' list
。我已尝试使用内置函数List.flatten和List.concat,但它们不起作用,它们需要'c list list
类型。有人能帮助我吗?
答案 0 :(得分:2)
您必须使用List.split
和List.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)
(fst
和snd
分别返回一对的第一个和第二个组成部分) flatten2'
将单独展平这两个组件。 flatten2
最终将满足您的需求。您也可以将其打包成一个函数,但我认为这更容易理解。
请注意,List.map
和List.flatten
都不是尾递归的;如果您需要尾递归版本,还有其他库可以使用它们,或者您可以使用rev_xxx
函数从标准库构建它们,或者从头开始编写它们。