fold_right给出了从列表尾部开始的值,但是我想给fold_right一个函数作为参数,这样该函数将从列表的头部开始收集值。
我希望iter
接收以列表头部开头的值。
持续传递是关键字......。提出问题的另一种方法是如何fold_left
与fold_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
答案 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"];;
给我们
如何
是
在