【问题标题】:Generating list of integers in OCaml without recursion在没有递归的情况下在 OCaml 中生成整数列表
【发布时间】:2016-04-20 17:37:34
【问题描述】:

如何使用其中一个折叠函数来生成从 0 到值 n-1 的整数列表?我对如何让 fold_right 返回一个列表而不是只返回一个累积值感到困惑。

这是一个帮助函数,我试图定义它来解决更大的问题。这是我的尝试:

-我知道基本情况必须是一个仅包含零的列表,因为我不想添加任何小于零的内容。
-我知道我需要减少 n 的值,以便我可以将 n-1 到 0 的数字放入列表中。

let buildList n = 
  let ibuildList elem list =
    list@[n-1]
  in List.fold_right ibuildList n [0];;

但我得到一个错误,在最后一行中用“n”下划线表示表达式的类型为 int,但表达式的类型应为 'a list。 n 不是我通过 [n-1] 变成列表的整数吗?我哪里做错了?

【问题讨论】:

    标签: list ocaml fold


    【解决方案1】:

    非常抱歉,我错过了至少一个推理步骤。

    折叠用于遍历集合。由于您想要生成一个列表并且您只有n,而不是一个集合,因此您不能以任何合理的方式真正使用折叠。其实你想做的更像是展开。即,您想将您的 n 展开到列表中。

    这个函数写起来容易,用折叠写起来不容易。

    以下是 OCaml 中展开的实现:

    let rec unfold_right f init =
        match f init with
        | None -> []
        | Some (x, next) -> x :: unfold_right f next
    

    以下是如何使用unfold_right 生成整数列表:

    let range n =
        let irange x = if x > n then None else Some (x, x + 1) in
        unfold_right irange 1
    

    这是运行range 时的样子:

    # range 0;;
    - : int list = []
    # range 8;; 
    - : int list = [1; 2; 3; 4; 5; 6; 7; 8]
    # range 5;;
    - : int list = [1; 2; 3; 4; 5]
    

    【讨论】:

    • 能否请您发布几个累积值不仅仅是整数的例子?
    • 我加了两个例子;我希望其中至少有一个有用:-)
    • 好吧,一直在玩代码。有点迷茫。我用其中的一些代码和我面临的问题更新了我的初始问题。谢谢!
    • 对不起,我没有考虑到你的问题。我道歉。我从一个更好的答案开始。
    • 你说这个函数写起来很简单,我可以用递归来做,但是我正在准备一个测试,我将无法在它上面使用递归。 (试图让我们使用高阶函数。)
    【解决方案2】:

    另一个版本,使用标准的Stream 模块:

    (* an infinite stream of natural numbers, starting from 0 *)
    let nats =
      let rec nats_from n = [< 'n; nats_from (n + 1) >]  (* extra syntax *)
      in nats_from 0
    
    (* the first n natural numbers: [0; n-1] *)
    let range n = Stream.npeek n nats
    

    [&lt; 'n; nats_from (n + 1) &gt;] 表示一个 lazy 列表,n 作为其头部,下一个自然数作为其尾部。 Stream.npeek n stream 使用 stream 的第一个 n 元素并将它们作为列表返回。

    使用utop 进行测试:

    utop # #load "dynlink.cma";; (* you need these to work with *) 
    utop # #load "camlp4o.cma";; (* the Stream's syntactic extension *)
    
    utop # range 1;;
    - : int list = [0]    
    
    utop # range 5;;
    - : int list = [0; 1; 2; 3; 4]
    
    utop # range 10;;
    - : int list = [0; 1; 2; 3; 4; 5; 6; 7; 8; 9]
    

    如果您想编译它,请使用以下命令(您需要使用 camplp4o 预处理器):

    $ ocamlc -pp camlp4o <filename>.ml 
    

    $ ocamlopt -pp camlp4o <filename>.ml 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-24
      • 2012-09-14
      相关资源
      最近更新 更多