在Ocaml中使用fold_right进行迭代

时间:2017-01-21 16:33:13

标签: ocaml

fold_right给出了从列表尾部开始的值,但是我想给fold_right一个函数作为参数,这样该函数将从列表的头部开始收集值。 我希望iter接收以列表头部开头的值。

持续传递是关键字......。提出问题的另一种方法是如何fold_leftfold_right

let fold f ls acc = List.fold_right f ls acc

val iter : ('a -> unit) -> 'a t -> unit

let iter f my_type =  
    let rec iiter my_type return = 
        return (fold (fun x y -> f x) my_type ()) () in iiter my_type (fun x y -> ())

但是当我打电话时:

iter (fun a -> print_string a) ["hi";"how";"are";"you"];;

输出:

  

youarehowhi

我需要

  

hihowareyou

4 个答案:

答案 0 :(得分:1)

这很简单,您必须尝试匹配行为的签名。

迭代不接受任何输入,并返回unit,而fold接受输入并返回相同类型的输出。现在,如果折叠所做的输入是unit,那么你将有一个折叠函数,它通过传递一个额外的unit并返回unit来对集合的每个元素应用一个函数。 },它基本上对应于正常迭代,例如:

# let foo = [1;2;3;4;5];;
# List.fold_left (fun _ a -> print_int a; ()) () foo;;
12345- : unit = ()

正如您所看到的,fold函数忽略了第一个参数,并始终返回unit

答案 1 :(得分:1)

在这种情况下,您需要通过fold的延续是一个函数,一旦被调用,将遍历列表的其余部分。

编辑:像这样:

let iter f list = fold
  (fun head iter_tail -> (fun () -> f head;; iter_tail ()))
  list
  ()

答案 2 :(得分:1)

fold_left类似于List.fold_left,但是使用List.fold_right(非尾递归)构造:

let fold_left f a l = List.fold_right (fun b a -> f a b) (List.rev l) a ;;

不是一个好主意,因为fold_left不是尾递归的,List.fold_left是尾递归的。最好将fold_right(tail-recursive)生成为:

let fold_right f l a = List.fold_left (fun a b -> f b a) a (List.rev l) ;;

如果你不能使用List.rev:

let rev l =
  let rec aux acc = function
    | []    -> acc
    | a::tl -> aux (a::acc) tl
  in
  aux [] l
;;

iter使用fold_left:

let iter f op = ignore (fold_left (fun a b -> f b;a) [] op ) ;;

测试:

# fold_left (fun a b -> (int_of_string b)::a ) [] ["1";"3"];;
- : int list = [3; 1]
# rev [1;2;3];;
- : int list = [3; 2; 1]
# iter print_string  ["hi";"how";"are";"you"];;
hihowareyou- : unit = ()

答案 3 :(得分:1)

let fold_left f init ls =
        let res = List.fold_right (fun a b acc -> b (f acc a)) ls (fun a -> a)
        in res init

现在正在呼叫

fold_left (fun a b -> Printf.printf "%s\n" b) () ["how";"are";"you"];;

给我们

  

如何