{OCaml] 頭の悪い無限リスト
Haskellのようなやつ。書いて書けないことはなかった。面倒ですが。
type 'a item = E | S of ('a * ('a inflist)) and 'a inflist = 'a item lazy_t;; let rec take : int -> 'a inflist -> 'a inflist = fun n list -> if n = 0 then lazy E else match Lazy.force list with | E -> lazy E | S (x, xs) -> lazy (S (x, take (n - 1) xs));; let rec print_inflist : ('a -> unit) -> 'a inflist -> unit = fun print list -> match Lazy.force list with | E -> () | S (x, xs) -> print x; print_inflist print xs;; let rec progression : int -> int -> int inflist = fun step start -> lazy (S (start, progression step (start + step)));; print_inflist (fun x -> print_int x; print_newline ()) (take 10 (progression 1 1));; let from_inflist : 'a inflist -> 'a Stream.t = fun list -> let top = ref list in Stream.from (fun _ -> match Lazy.force !top with | E -> None | S (x, xs) -> top := xs; Some x);; let s = from_inflist (progression 1 1) in let i = ref (Stream.npeek 10 s) in while !i <> [] do match !i with | [] -> failwith "END"; | x :: xs -> print_int x; print_newline (); i := xs done;;
何が面倒ってlazy (S (x, y))を演算子に閉じ込めてx ^:: yなんて書きたいと思ってもそうするとlazyではなくなるため目的を達成できなくなるため毎回lazy (S (x, y))って書かないといけないところです。