如何在ocaml中的精细功能上使用折叠

时间:2018-10-06 15:22:33

标签: tuples ocaml fold

正如标题所示,我想使用折叠。如果我理解正确,它曾经将功能应用于列表中的每个项目。这就是我想对函数执行的操作,但是我不知道如何格式化它。

这是我想与fold一起使用的功能:

let pairing list =
let rec aux counter length paired list = match list with
| [] -> paired
| [head] -> paired
| head :: head' :: tail -> if counter = length then aux (counter-1) length ((head, head) :: paired) (head :: head' :: tail) else aux counter length ((head, head') :: paired) (head' :: tail)
in List.rev(aux (List.length(listheads list)) (List.length(listheads list)) [] (listheads list));;

它的作用是返回配对在一起的列表中所有项目的列表。

例如,如果我的列表是[3;4;2],它应该返回

[(3,3); (3,4); (3,2); (4,3); (4,4); (4,2); (2,3); (2,4); (2,2)]

此刻返回的只是[(3,3); (3,4); (3,2)],因为该函数仅适用于列表的第一项。

这是所有帮助器功能:

let rec member list x = match list with
| [] -> false
| head :: tail -> head = x || member tail x

let head_list list =
let rec aux l1 list = match list with
 | [] -> l1
 | (x,y) :: tail -> aux (x :: l1) tail
in List.rev (aux [] list);;

let head'_list list =
let rec aux l2 list = match list with
 | [] -> l2
 | (x,y) :: tail -> aux (y :: l2) tail
in List.rev (aux [] list);;

let listheads list =
let rec aux returnlist l1 l2 = match l1 with
| [] -> returnlist
| head :: tail -> if member l2 head = true && member returnlist head = false then aux (head :: returnlist) tail l2 else aux returnlist tail l2
in List.rev(aux [] (head_list list) (head'_list list));;

listheads所做的是将使用我的原始列表(例如[(3,4); (4,2); (2,3); (4,7); (9,4)]),使用head_listhead'_list来确定{{1 }}和head放在元组中,并将它们放在列表中(在我给出的情况下,head')。

我知道[3;4;2]带有一个函数,一个空列表和一个列表作为参数,但是我不知道如何使用fold配对。

2 个答案:

答案 0 :(得分:0)

很难回答您的问题,因为没有干净的地方可以折叠来获得想要的结果。

仅调试代码可能会更富有成果。在我看来,您正在倒退使用计数器。它的初始值是列表的长度,并且对于每个递归调用都会减小。但是您的终止测试会根据列表的长度进行测试。在我看来,您应该针对0(或可能为1)进行测试。

如果您有一个函数f,该函数对某个值执行了一些有趣的操作,并且有一个值列表,则可以使用List.map来获取{{1}的值列表}应用于列表的每个元素。您不需要为此折叠。

折叠的目的是计算除函数值列表以外的东西。例如,如果每次对f的调用都构成一个值列表,则可以使用折叠将这些列表并置为更长的列表。

假设f将值f放入列表x中。然后,您可以创建一个(反向)加倍列表,如下所示:

[x; x]

如果您可以使用let f x = [x; x] let double l = let aux sofar x = f x @ sofar in List.fold_left aux [] l # double [1;2;3];; - : int list = [3; 3; 2; 2; 1; 1] 之类的函数将值转换为列表,则可以遵循此模式。如果您在外部函数中定义f,则可以访问初始列表。

答案 1 :(得分:0)

您的代码需要在列表上进行两次通过

   let pairing l =
     let second_pass x acc y = ......  in
     let first_pass  acc el = .......  in
     List.fold_left first_pass [] l |> List.rev

第一次通过函数应调用第二次通过函数,第二次通过函数将创建对元素。免费完成这两个功能的代码。

这是我得到的结果:

    utop # pairing [3 ; 4 ; 2];;
    - : (int * int) list =
    [(3, 3); (3, 4); (3, 2); (4, 3); (4, 4); (4, 2); (2, 3); (2, 4); (2, 2)]