Ocaml:懒惰列表

时间:2009-10-27 16:17:20

标签: stream ocaml lazy-evaluation

如何制作一个代表一系列倍数的惰性列表?例如:

1 2 4 8 16 32

4 个答案:

答案 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

这是处理此问题的标准库。

这个问题也与这个问题非常相似:

What OCaml libraries are there for lazy list handling?

答案 2 :(得分:3)

此外,我的OCaml Network Application Environment核心基金会中有一个名为Cf_seq的惰性列表模块。事实上,我写了一整套功能数据结构。这些都是根据2条款BSD许可证提供的。享受。

更新:代码已重命名为“Oni”,现在它已在BitBucket上托管。您也可以使用GODI包。

答案 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