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

时间:2016-04-17 20:09:52

标签: list ocaml fold

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

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

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

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

但是我得到了一个错误,强调了#34; n"在最后一行中说表达式是int类型但是表达式需要类型'列表。我不是通过[n-1]变成列表的整数吗?我哪里出错了?

2 个答案:

答案 0 :(得分:2)

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

折叠用于遍历集合。既然你想要生成一个列表而你只有n而不是一个集合,那么你就无法以任何合理的方式使用fold。事实上,你想要做的更像是展开。即,您想将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]

答案 1 :(得分:1)

替代版本,使用标准Stream模块:

[< 'n; nats_from (n + 1) >]

作品n代表 lazy 列表,其中Stream.npeek n stream为其头部,下一个自然数字为尾部。 n使用stream的第一个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] 元素并将其作为列表返回。

使用utop进行测试:

$ ocamlc -pp camlp4o <filename>.ml 

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

$ ocamlopt -pp camlp4o <filename>.ml 

foos = new Foo[10];