関数クロージャーは本質的に遅延値と同等であることに注意してください。
lazy n : 'a Lazy.t <=> (fun () -> n) : unit -> 'a
force x : 'a <=> x () : 'a
したがって、型'a llist
は次と同等です
type 'a llist = 'a cell Lazy.t
つまり、遅延セル値です。
マップの実装は、上記の定義に関してより意味があるかもしれません
let rec map f lst =
match force lst with
| Nil -> lazy Nil
| Cons (hd,tl) -> lazy (Cons (f hd, map f tl))
それをクロージャーに戻すと、次のようになります。
let rec map f lst =
match lst () with
| Nil -> (fun () -> Nil)
| Cons (hd,tl) -> (fun () -> Cons (f hd, map f tl))
同様に追加
let rec append a b =
match force a with
| Nil -> b
| Cons (hd,tl) -> lazy (Cons (hd, append tl b))
になる
let rec append a b =
match a () with
| Nil -> b
| Cons (hd,tl) -> (fun () -> Cons (hd, append tl b))
lazy
何が起こっているのかがより明確になるため、私は通常、構文を使用することを好みます。
また、レイジー サスペンションとクロージャーは厳密には同じではないことに注意してください。例えば、
let x = lazy (print_endline "foo") in
force x;
force x
版画
foo
一方
let x = fun () -> print_endline "foo" in
x ();
x ()
版画
foo
foo
違いは、式の値を1 回だけforce
計算することです。