2015-12-10 32 views
2

假設我們有這樣一個懶惰的名單:是否有意義或者是有可能寫懶惰列表`iter`功能?

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

不,它並沒有太大的意義。

首先,你可能注意到了這一點,所有的名單是無限的(你沒有空元素)。所以,只有你的類型的居民的例子以某種方式使用遞歸函數,例如。 :

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())) 

注意如何遞歸調用地圖是「受保護」的「樂趣() - >」,所以它不會觸發「馬上」但每次你的懶惰列表的尾部被強制。

您可以用這個來無限流懶洋洋地計算,例如:

let evens = map ((*) 2) omega 

計算流[0; 2; 4; 6; 8; ...

注意,你可以使用它通過映射,做了side_effect如函數來實現某種形式的「ITER」的。

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 

(我沒有試過代碼,所以可能會有一些錯別字)。