假设我们有这样一个懒惰的名单:
type 'a lazy_list_t = Cons of 'a * (unit -> 'a lazy_list_t)
在常规列表中使用iter
之类的函数是否有意义:
val iter : ('a -> unit) -> 'a list -> unit
List.iter f [a1; ...; an] applies function f in turn to a1; ...; an. It is equivalent to begin f a1; f a2; ...; f an; () end.
或者是否可以生成iter_lazy
之类的
val iter_lazy: ('a -> unit) -> 'a lazy_list -> unit
答案 0 :(得分:1)
不,这没有多大意义。
首先,您可能已经注意到它,您的所有列表都是无限的(您没有空元素)。所以,只有你的类型的居民的例子以某种方式使用递归函数,例如。 :
let omega =
let rec f n = Cons (n, fun () -> f (n + 1)) in
f 0
这实现了无限流[0,1,2,3,...
如果你想要一个不同的程序你可以实现:
let rec iter f (Cons (n, g)) = f n; iter f (g ())
但是如果你做iter print_int omega
,它将导致输出所有整数,这需要一些时间。
所以itering不是一个选择。什么是有效的"映射",你可以实现这个功能:
val map: ('a -> 'b) -> 'a lazy_list_t -> 'b lazy_list
let rec map f (Cons (x, g)) = Cons (f x, fun () -> map f (g ()))
注意对地图的递归调用是如何受到保护的"通过" fun() - >"所以它不会立即触发""但只有每次强制你的懒惰列表的尾部。
您可以使用它来懒惰地计算无限流,例如:
let evens = map ((*) 2) omega
计算流[0; 2; 4; 6; 8; ...
请注意,您可以使用它来实现某种类型的" iter"通过映射执行side_effect的函数,例如。
let units = map print_int evens
将立即输出数字" 0"并输出流[(); (); (); ......每次你强迫其中一个"尾巴"这个流将输出相应的数字(它可以多次发生)。例如:
(* Force the tail *)
val tl : 'a lazy_list_t -> 'a lazy_list_t
let tl (Cons (_, g)) = g ()
let () = begin
tl units; (* ouputs "2" *)
tl (tl units); (* outputs "24" *)
tl units; (* outputs "2" *)
end
(我还没有尝试过代码,所以可能会有一些拼写错误)。