我正在尝试扩展朋友的OCaml计划。这是一些数据分析所需的大量函数。由于我不是一个真正的OCaml破解,我现在仍然坚持(对我来说)奇怪的List实现:
type 'a cell = Nil
| Cons of ('a * 'a llist)
and 'a llist = (unit -> 'a cell);;
我发现这实现了某种“懒惰”列表,但我完全不知道它是如何工作的。我需要基于上面的类型实现Append和Map Function。有人知道怎么做吗?
真的很感激任何帮助!
答案 0 :(得分:7)
let rec append l1 l2 =
match l1 () with
Nil -> l2 |
(Cons (a, l)) -> fun () -> (Cons (a, append l l2));;
let rec map f l =
fun () ->
match l () with
Nil -> Nil |
(Cons (a, r)) -> fun () -> (Cons (f a, map f r));;
这种懒惰列表实现的基本思想是每个计算都通过fun() - >封装在一个函数中(技术术语是一个闭包)。 X。 然后仅在函数应用于()(单位值,不包含任何信息)时才计算表达式x。
答案 1 :(得分:7)
可能有助于注意函数闭包基本上等同于惰性值:
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
不同之处在于force
只计算表达式的值。
答案 2 :(得分:1)
是的,列表可以是无限的。其他答案中给出的代码将附加到无限列表的末尾,但是没有可编写的程序,而不能观察无限列表后附加的内容。