【问题标题】:Lazy list of x, f x, f (f x),x, f x, f (f x) 的惰性列表,
【发布时间】:2017-04-30 05:39:32
【问题描述】:

Batteries.LazyList 允许定义惰性列表。我想定义一个惰性列表,由xf xf (f x)f (f (f x))等组成。

根据模块文档中的 cmets,看来 from_loop 是我想要的功能:

from_loop data next 从将next 应用到data,然后应用到结果等的连续结果中创建一个(可能是无限的)惰性列表。”

这个描述表明,如果我想要一个非负整数的惰性列表,例如,我可以这样定义它:

let nat_nums = from_loop 0 (fun n -> n + 1)

但是,这失败了,因为from_loop 的签名是

'b -> ('b -> 'a * 'b) -> 'a LazyList.t

所以next 函数具有签名('b -> 'a * 'b)。在 utop 中,错误消息下划线 n + 1 并说

Error: This expression has type int but an expression was expected of type 'a * int

我不明白'a 应该是什么。为什么next 函数应该返回一对?为什么列表的类型应该是'a LazyList.t?元素的类型不应该与next 函数的参数类型相同吗?函数的描述并没有让我明白答案。


如果它有帮助,我对我正在尝试做的事情的概念来自 Clojure 的 iterate。在 Clojure 中,我可以像这样创建上述定义:

(def nat-nums (iterate (fn [n] (+ n 1)) 0))

【问题讨论】:

    标签: ocaml lazy-sequences ocaml-batteries


    【解决方案1】:

    传递给from_loop 的函数必须返回一对。该对的第一个元素是您要返回的值。该对的第二个元素是稍后计算 next 元素所需的状态。

    您的代码:

    (fun n -> n + 1)
    

    只计算惰性列表的下一个元素,它不返回下一次调用所需的状态。像这样的东西就是我们想要的:

    (fun n -> (n, n + 1))
    

    (这将返回一个以 0 开头的列表,我认为这是您想要的。)

    此公式比您的 clojure 示例更灵活,因为它允许您保持与返回值不同的任意状态。状态的类型为 'b,与您为 from_loop 指定的类型相同。

    我现在没有电池,所以无法尝试。但我认为根据类型是正确的。

    【讨论】:

    • 谢谢杰弗里。我根据您写的内容做了一些实验,这似乎是正确的变体:LazyList.from_loop 0 (fun n -> (n, n+1))。如果我对这对的两个元素都使用n+1,那么第一个元素最终是 1 而不是 0。
    • (我已经解决了这个问题,我做了一些这样的小修改。抱歉移动了目标。)
    • 啊,对。谢谢。并感谢您解释为什么会返回一个单独的状态。非常好。我看到了它的价值。 (移动目标没问题。我也总是在发布后编辑。可能应该等待评论。)
    【解决方案2】:

    原来我真正想要的函数是LazyList.seq,而不是from_loop。虽然from_loop 有其用途,但seq 更简单并且可以满足我的需求。唯一的技巧是你必须提供第三个参数,它是一个终止测试,当列表应该结束时返回 false。我想要一个无限的列表。可以使用始终返回 true 的终止函数来创建它:

    let nat_nums = seq 0 (fun n -> n + 1) (fun _ -> true);;
    LazyList.to_list (LazyList.take 8 nat_nums);;
    - : int list = [0; 1; 2; 3; 4; 5; 6; 7]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-18
      • 1970-01-01
      • 2021-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多