在 OCaml 中创建列表的代码有什么问题?

问题描述 投票:0回答:3

我正在尝试在 OCaml [randlist len max] 中创建一个程序,它将生成一个长度为 len 且整数小于 max 的 int 列表。

我想知道以下代码有什么问题:

let randlist dolzina maksimum =
  let rec aux dolz maks acc =
    match (List.length acc) with
    | dolz -> acc
    | _ -> aux dolz maks ((Random.int maks) :: acc)
  in
  aux dolzina maksimum []

这总是返回一个空列表,我不明白为什么。

另一件让我困惑的事情是以下代码出了什么问题:

let randlist dolzina maksimum =
  Random.self_init ()
  let rec aux dolz maks acc =
    match (List.length acc) with
    | dolz -> acc
    | _ -> aux dolz maks ((Random.int maks) :: acc)
  in
  aux dolzina maksimum []

一旦我添加 Random.self init (),整个代码就会崩溃。 Random.self_init 到底有什么作用,何时以及如何使用它?

function random functional-programming ocaml
3个回答
3
投票

您使用

match
就好像它要比较两个整数值,但这不是它的工作原理。本场比赛:

Match List.length acc with
| dolz -> ...

将始终匹配第一个案例。名称

dolz
是一个与列表长度绑定的新变量。
dolz
的外部定义与此处无关,模式引入了 new 名称。

如果你想比较两个整数值,你应该使用

if
:

if List.length acc = dolz then
    ...
else
    ...

1
投票

模式匹配将与模式匹配的值解构为更小的部分,它不测试相等性。换句话说,你的第一个案例

match List.length acc with
| dolz -> acc

读取:获取

List.length acc
返回的值,将其命名为箭头
dolz
右侧的
->
,然后运行
->
后面的代码。请注意,这意味着
dolz
匹配任何值。 这就是为什么编译器警告你第二种情况

| _ -> aux dolz maks ((Random.int maks) :: acc)

从未使用过。

对于你的第二个问题,代码不会崩溃,因为你的代码类型不正确,因此无法编译。

Random.self_init
初始化PRNG的种子。您应该在程序中调用它一次,而不是每次调用
randlist
时都调用它。


0
投票

您想要完成的事情可以实现,而无需计算累积列表的长度。您只需在每次迭代时将长度参数减一,并在小于或等于

acc
时返回
0

let randlist count max =
  let rec aux c m acc =
    if c <= 0 then acc
    else aux (c-1) m (Random.init max :: acc)
  in
  aux count max []

当然,这一切只是一种复杂的写法:

let randlist count max =
  List.init count (fun _ -> Random.int max)

这里

List.init
函数为我们处理迭代。实现一个等效的函数可能会揭示它的工作原理。

let list_init n f =
  let rec list_init' n f acc = 
    if n <= 0 then acc 
    else list_init' (n-1) f (f (n-1) :: acc)
  in
  list_init' n f []

或者利用

tail_mod_cons
来避免使用具有显式累加器的辅助函数:

let[@tail_mod_cons] list_init n f =
  if n <= 0 then []
  else 
    let r = f n in
    r :: list_init f (n - 1)

这与

List.init
实际上实现的方式非常相似。

let[@tail_mod_cons] rec init i last f =
  if i > last then []
  else if i = last then [f i]
  else
    let r1 = f i in
    let r2 = f (i+1) in
    r1 :: r2 :: init (i+2) last f

let init len f =
  if len < 0 then invalid_arg "List.init" else
  init 0 (len - 1) f
© www.soinside.com 2019 - 2024. All rights reserved.