(* implementation by function closures *) type 'a lflist = LFNil | LFCons of 'a * (unit -> 'a lflist);; let rec lfzip = function | LFNil, LFNil -> LFNil | LFCons (a1, lf1), LFCons (a2, lf2) -> LFCons ((a1, a2), fun () -> lfzip (lf1 (), lf2 ())) | _ -> raise (Invalid_argument "lfzip") ;; let rec lfmap f = function | LFNil -> LFNil | LFCons (a, lf) -> LFCons (f a, fun () -> lfmap f (lf ())) ;; let rec lffib = LFCons (1, fun () -> lfmap (fun (a,b)-> a+b) (lfzip (lffib, LFCons (1, fun () -> lffib)))) ;; let rec lftake n = function | LFCons (a, lf) when n > 0 -> a::(lftake (n-1) (lf ())) | _ -> [] ;; (* implementation by native lazy values *) type 'a llist = LNil | LCons of 'a * 'a llist lazy_t;; let rec lzip = function | LNil, LNil -> LNil | LCons (a1, ll1), LCons (a2, ll2) -> LCons ((a1, a2), lazy (lzip (Lazy.force ll1, Lazy.force ll2))) | _ -> raise (Invalid_argument "lzip") ;; let rec lmap f = function | LNil -> LNil | LCons (a, ll) -> LCons (f a, lazy (lmap f (Lazy.force ll))) ;; let rec lfib = LCons (1, lazy (lmap (fun (a,b)-> a+b) (lzip (lfib, LCons (1, lazy lfib))))) ;; let rec ltake n = function | LCons (a, ll) when n > 0 -> a::(ltake (n-1) (Lazy.force ll)) | _ -> [] ;;