是否有意义或是否可以为懒惰列表编写`iter`函数?

时间:2015-12-10 08:28:01

标签: ocaml

假设我们有这样一个懒惰的名单:

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

1 个答案:

答案 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

(我还没有尝试过代码,所以可能会有一些拼写错误)。