0

我正在尝试在 OCaml 中编写一个简单的函数

let rec pell (i: int) =
(if i <= 2 then i (*if given n is less tahn 2 then return 2, else return previous n-1 th term and n-2 nd term recursively*)
  else if i>2 then
  2 * pell i - 1 + pell i - 2

else failwith "unimplemented" (*else fail with unimplemented message*)
);;

编写之前的 pell 函数的无限精度版本

pell2 0 = []

pell2 1 = [1]

pell2 7 = [9; 6; 1]

pell2 50 = [2; 2; 5; 3; 5; 1; 4; 2; 9; 2; 4; 6; 2; 5; 7; 6; 6; 8; 4]

我为此编写了以下代码:

let rec pell2 i =

(if i <= 2 then
  [] -> i;
  else if i=0 then [];
  else if i>2 then                                (*finding pell number and using sum function to 
output list with infinite precision...*)
  [] -> pell2 i-1 + pell2 i-2;

else failwith "unimplemented"

);;

但仍然有一些语法错误。有人可以帮我解决这个问题吗?

4

2 回答 2

0
if i <= 2 then
     [] -> i

在这样的片段中,->是无效的。看起来您可能正在将模式匹配与match ... with ...if/else up 混合在一起。

此外,您首先检查是否i小于或等于 2,然后您需要else测试i是否等于 0。第一次检查意味着第二次永远不会发生。

于 2021-02-25T18:10:32.780 回答
0

首先,让我们看一下输出的示例pell2。我们看到它pell2有一个整数参数,并返回一个整数列表。因此,我们知道我们要创建的函数具有以下类型签名:

pell2: int -> int list

修复(部分但不是全部)语法错误并尝试维护您的逻辑,

let rec pell2 i =
  if i=0 then []
  else if i <= 2 then i
  else if i>2 then pell2 i-1 + pell2 i-2

请注意,我删除了每个表达式末尾的分号,因为 OCaml 在其语法中使用分号专门用于处理计算结果为 unit 的表达式()。请参阅 ivg 对此的出色解释。这段代码的主要缺陷是它不进行类型检查。我们看到我们有条件地返回一个列表,否则返回一个int. 请注意上面我们如何定义 pell2 应该返回一个int list. 因此,我们可以通过将int结果包装在列表中来开始解决此问题:

let rec pell2 n = 
  if n = 0 then []
  else if n <= 2 then [n]
  else ... something that will return the Pell number as a list ...

正如您已经写过的,else可以使用对 pell2 函数的递归调用来编写分支。但是,我们不能像您之前那样编写它,因为 pell2 计算结果为一个列表,而二元运算符+仅适用于两个整数。所以,我们将不得不定义我们自己的求和列表的方式。调用 this sum_lists,我们得到以下代码: 我们现在可以完全定义我们的函数 pell2:

let rec pell2 n =
  if n = 0 then []
  else if n <= 2 then [n]
  else (* Pell(n) = (2 * Pell(n-1)) + Pell(n-2) *)
    let half_of_first_term = pell2 n-1 in
    let first_term = sum_lists half_of_first_term half_of_first_term in
    let second_term = pell2 n-2 in
    sum_lists first_term second_term

因此,剩下的就是定义 sum_lists,以便我们正确地将两个与 pell2 的返回类型格式相同的列表相加。sum_lists 的签名是

sum_lists: int list -> int list -> int list

我将给出实现的基本概述,但剩下的留给你自己弄清楚,因为这是分配问题的主要症结所在。

let sum_lists lst1 lst2 =
  let rec sum_lists_helper lst1 lst2 carry =  
    match lst1, lst2 with
    | [], [] -> if carry = 1 then [1] else []
    | h::t, []
    | [], h::t -> ...
    | h1::t1, h2::t2 -> ...
  in
  sum_lists_helper lst1 lst2 0
于 2021-02-25T19:09:49.467 回答