将序列转换为OCaml中的列表的函数

时间:2018-04-08 05:54:38

标签: ocaml

我想使用List.init将序列转换为列表。我想在每一步检索s的第i个值。

let to_list s = 
  let n = length s in List.init n (fun _i -> match s () with
    |Nil -> assert false
    |Cons(a, sr) -> a)

这给了我一个仅用s的第一个元素初始化的列表。是否有可能在OCaml中使用s的所有值初始化列表,需要帮助请求(抱歉begginer问题-_-)

谢谢

3 个答案:

答案 0 :(得分:3)

问题的实质是你没有保存sr,这会让你检索序列的下一个元素。

但是,稍微大一点的问题是List.init只将int作为参数传递给初始化函数。因此,即使您确实跟踪sr,也无法将其传递给初始化函数。

你可以使用OCaml的不纯部分做你想做的事。例如,您可以在每个步骤中将sr保存在全局引用变量中,并在下次调用初始化函数时检索它。但是,生成列表实际上这是一种非常麻烦的方式。

我建议使用List.init。您可以编写一个简单的递归函数来执行您想要的操作。 (如果你关心尾递归,你可以写一个稍微简单的函数。)

答案 1 :(得分:3)

研究List.init的{​​{3}}可能有所帮助。

根据列表的大小,有两种变体:尾递归的init_tailrec_aux,其结果的顺序相反,基本的init_aux。它们具有相同的结果,因此我们只需要查看init_aux

let rec init_aux i n f =
  if i >= n then []
  else
    let r = f i in
    r :: init_aux (i+1) n f

此函数以递归方式递增计数器i,直到达到限制n。对于严格小于限制的计数器的每个值,它将f i给出的值添加到正在生成的列表的头部。

现在的问题是,当使用i的不同值调用时,您的匿名函数会执行什么操作?:

let f_anon =
  (fun _i -> match s () with
      |Nil -> assert false
      |Cons(a, sr) -> a)

无论_i如何,它总是给出s ()生成的列表的头部,而如果 s ()总是返回相同的列表,那么{{ 1}} = f_anon 0 = f_anon 1 = f_anon 2 = f_anon 3

杰弗里·斯科菲尔德definition描述了一种在每个hd (s ())给出不同价值的技巧,我同意他的建议_i不是解决这个问题的最佳方法

答案 2 :(得分:0)

使用递归函数会增加复杂性,所以我认为直接初始化相应长度的列表(或数组)会更好,但我真的不知道如何在每个_i像Jeffrey那样得到不同的值斯科菲尔德说我对ocaml特别是序列并不熟悉,所以我在做这方面遇到了一些困难:(