如何制作一个代表一系列倍数的惰性列表?例如:
1 2 4 8 16 32
答案 0 :(得分:13)
使用流:
let f x = Stream.from (fun n -> Some (x * int_of_float (2.0 ** float_of_int n)))
或
let f x =
let next = ref x in
Stream.from (fun _ -> let y = !next in next := 2 * y ; Some y)
使用自定义lazy_list
类型:
type 'a lazy_list =
| Nil
| Cons of 'a * 'a lazy_list lazy_t
let rec f x = lazy (Cons (x, f (2*x)))
答案 1 :(得分:9)
伟大的博客获得了广泛的关于这一主题的文章:
http://enfranchisedmind.com/blog/posts/ocaml-lazy-lists-an-introduction/
您还可以查看http://batteries.forge.ocamlcore.org/doc.preview%3Abatteries-beta1/html/api/Lazy%5Flist.html
这是处理此问题的标准库。
这个问题也与这个问题非常相似:
答案 2 :(得分:3)
此外,我的OCaml Network Application Environment核心基金会中有一个名为Cf_seq
的惰性列表模块。事实上,我写了一整套功能数据结构。这些都是根据2条款BSD许可证提供的。享受。
答案 3 :(得分:2)
如果您想亲手操作,我会说您必须选择主要选项:
使用自定义lazy_list
类型,就像ephemient所说的那样(除了他的解决方案有点破解):
type 'a lazy_list =
| Nil
| Cons of 'a * 'a lazy_list
let head = function
| Nil -> failwith "Cannot extract head of empty list"
| Cons (h, _) -> h
let tail = function
| Nil -> failwith "Cannot extract tail of empty list"
| Cons (_, t) -> t
使用一种thunk(就像用于在不支持它的语言中实现延迟评估的东西)。您将列表定义为函数unit -> 'a
,该函数说明如何从当前元素中获取下一个元素(不需要使用流)。例如,要定义所有自然整数的列表,您可以执行
let make_lazy_list initial next =
let lazy_list current () =
let result = !current in
current := (next !current); result
in lazy_list (ref initial)
let naturals = make_lazy_list 0 (function i -> i + 1)
如果你这样做
print_int (naturals ());
print_int (naturals ());
print_int (naturals ())
您将获得以下输出:
0
1
2