在没有递归的情况下在 OCaml 中生成整数列表

Generating list of integers in OCaml without recursion

如何使用折叠函数之一生成从 0 到值 n-1 的整数列表?我很困惑如何让 fold_right 到 return 一个列表,而不是 return 只是一个累加值。

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

-我知道基本情况必须是一个只包含零的列表,因为我不想添加任何小于零的东西。
-我知道我需要减少值 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] 转换成列表的整数吗?我哪里错了?

非常抱歉,我至少漏掉了推理的一步。

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

写这个函数很容易,但是用fold写就不容易了

这是 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]

替代版本,使用标准 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

[< 'n; nats_from (n + 1) >]表示一个惰性列表,其中n为头,下一个自然数为尾。 Stream.npeek n streamstream 和 returns 的前 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