Ocaml:惰性列表

发布于 2024-08-09 12:51:52 字数 70 浏览 3 评论 0原文

如何制作一个表示加倍数字序列的惰性列表?例子:

1 2 4 8 16 32

How can I make a lazy list representing a sequence of doubling numbers? Example:

1 2 4 8 16 32

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

半世晨晓 2024-08-16 12:51:52

使用流:

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)))

Using streams:

let f x = Stream.from (fun n -> Some (x * int_of_float (2.0 ** float_of_int n)))

or

let f x =
  let next = ref x in
    Stream.from (fun _ -> let y = !next in next := 2 * y ; Some y)

Using a custom lazy_list type:

type 'a lazy_list =
  | Nil
  | Cons of 'a * 'a lazy_list lazy_t
let rec f x = lazy (Cons (x, f (2*x)))
离不开的别离 2024-08-16 12:51:52

另外,我的 OCaml 网络应用程序环境 中有一个名为 Cf_seq 的惰性列表模块核心基础。事实上,我写了一整套函数式数据结构。这一切都可以在 2 条款 BSD 许可证下使用。享受。

更新:代码已重命名为“Oni”,现在托管在位桶。您还可以使用 GODI 包。

Also, there is a lazy list module called Cf_seq in my OCaml Network Application Environment Core Foundation. In fact, I wrote a whole passle of functional data structures. It's all available under a 2-clause BSD license. Enjoy.

Update: the code has been renamed "Oni" and it's now hosted at BitBucket. You can also use the GODI package for it.

栩栩如生 2024-08-16 12:51:52

如果你想手动完成,我想说你必须主要选项:

  • 使用自定义的lazy_list类型,就像ephemient所说的那样(除了他的解决方案有点破损):

    输入 'lazy_list =
        |零
        | 'a * 'lazy_list 的缺点
    
    让头=函数
        |无 ->失败“无法提取空列表的头部”
        |缺点 (h, _) ->小时
    
    让尾=函数
        |无 ->失败“无法提取空列表的尾部”
        |缺点(_,t)-> t
    
  • 使用一种 thunk (就像用来实现惰性的东西 )以不支持它的语言进行评估)。您将列表定义为函数 unit -> 'a 说明如何从当前元素获取下一个元素(无需为此使用流)。例如,要定义所有自然整数的列表,您可以这样做

    让 make_lazy_list 初始 next =
        让lazy_list当前()=
            让结果 = !当前在
            当前:=(下一个!当前);结果
        在lazy_list中(参考初始值)
    
    让naturals = make_lazy_list 0(函数i -> i + 1)
    

    如果你这样做

    print_int(naturals());
    print_int(自然数());
    print_int(自然数())
    

    您将得到以下输出:

    <前><代码>0
    1
    2

If you want to do it by hand, I'd say you have to main options:

  • Use a custom lazy_list type, like ephemient said (except his solution is a bit broken):

    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
    
  • Use a kind of thunk (like the thing used to implement lazy evaluation in a language that does not support it). You define your list as a function unit -> 'a that says how to get the next element from the current one (no need to use streams for that). For example, to define the list of all natural integers, you can do

    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)
    

    The if you do

    print_int (naturals ());
    print_int (naturals ());
    print_int (naturals ())
    

    you will get the following output:

    0
    1
    2
    
傲鸠 2024-08-16 12:51:52

来自遥远未来的答案...

OCaml 4.07 引入了 Seq 模块< /a> 这可以促进这一点。

# let rec lazy_list start f () =
    Seq.Cons (start, lazy_list (f start) f);;
val lazy_list : 'a -> ('a -> 'a) -> 'a Seq.t = <fun>
# lazy_list 1 @@ ( * ) 2
  |> Seq.take 5 
  |> List.of_seq;;
- : int list = [1; 2; 4; 8; 16]

Answer from the distant future...

OCaml 4.07 introduced the Seq module which can facilitate this.

# let rec lazy_list start f () =
    Seq.Cons (start, lazy_list (f start) f);;
val lazy_list : 'a -> ('a -> 'a) -> 'a Seq.t = <fun>
# lazy_list 1 @@ ( * ) 2
  |> Seq.take 5 
  |> List.of_seq;;
- : int list = [1; 2; 4; 8; 16]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文