将列表从一个函数连接到 OCaml 中的另一个递归函数
Concatenating list from a function to another recursive function in OCaml
所以我尝试在 OCaml 中编写一个相对简单的函数,它接受一个整数 n 和一个最多为 5 的整数列表,然后将所述列表中大于 1 的所有整数重复 n 次。
我已经有一个现有的函数 repeat,无论我给它什么,它都会重复 n 次
let rec repeat : int -> 'a -> 'a list =
fun n a ->
match n with
| 0 -> []
| h -> a :: repeat (h-1) a ;;
下面是名为 Pentograph 的函数的代码
let pentograph : int -> int list-> int list =
fun n letter ->
match letter with
|[] -> []
|h::t -> if h>1 then List.concat[(repeat n h);pentograph n t] else List.conca[h;pentograph n t];;
我收到以下错误:
Error: Unbound value pentograph
在尝试使用 :: 运算符时我也遇到了错误,因为我无法使用它来连接 2 个列表。
请帮我想办法解决这个问题!
编辑:如果正确答案或更优化的答案使用 map 那么请用它来回答而不是试图修复我的代码。
Ocaml 中的列表是一种带有一些语法糖的变体类型,而不是典型的用户定义的变体类型。列表可以是一个空列表 ([]
),也可以是使用 ::
运算符附加到列表上的 'a
类型的某些元素。由于这是一种递归类型,因此我们使用递归来处理它们也就不足为奇了。
也可以使用 @
运算符连接列表。
你的repeat
功能不错。我将省略显式类型并稍微重新格式化它:
let rec repeat n a =
match n with
| 0 -> []
| _ -> a :: repeat (n - 1) a
您已经定义了退出条件。如果我们要求函数重复某些内容 0
次,我们会得到一个空列表。否则,我们将 a
添加到重复函数少一次的结果的前面。第二阶段设置状态更新,使其更接近退出条件。
repeat 4 6
6 :: repeat 3 6
6 :: 6 :: repeat 2 6
6 :: 6 :: 6 :: repeat 1 6
6 :: 6 :: 6 :: 6 :: repeat 0 6
[6; 6; 6; 6]
因此,对 pentograph
函数执行相同的操作。需要多次重复,和一个列表。我们可以递归地遍历列表,所以自然退出条件是一个空列表。如果列表为空,则结果应为空列表。
let rec pentograph n lst =
match lst with
| [] -> []
否则列表将是一些值和列表的剩余部分。
let rec pentograph n lst =
match lst with
| [] -> []
| x::xs -> ...
现在我们知道x
是列表的第一个元素,所以我们可以检查它是否大于1。
let rec pentograph n lst =
match lst with
| [] -> []
| x::xs ->
if x > 1 then ...
else ...
如果它大于 1,我们会将重复工作外包给 repeat
,并将其添加到列表其余部分 运行 宁 pentograph
的前面。如果不是,我们将只 运行 列表其余部分的 pentograph
函数,忽略结果中的 x
。
let rec pentograph n lst =
match lst with
| [] -> []
| x::xs ->
if x > 1 then
repeat n x :: pentograph n xs
else
pentograph n xs
现在,让我们尝试评估一下 pentograph 2 [1; 2; 3]
。
pentograph 2 [1; 2; 3]
pentograph 2 [2; 3]
repeat 2 2 :: pentograph 2 [3]
repeat 2 2 :: repeat 2 3 :: pentograph 2 []
repeat 2 2 :: repeat 2 3 :: []
[2; 2] :: [3; 3] :: []
[[2; 2]; [3; 3]]
现在,您可能正在寻找的结果是 [2; 2; 3; 3]
,因此我们可以用列表 concatenation.
替换列表构造
let rec pentograph n lst =
match lst with
| [] -> []
| x::xs ->
if x > 1 then
repeat n x @ pentograph n xs
else
pentograph n xs
现在:
pentograph 2 [1; 2; 3]
pentograph 2 [2; 3]
repeat 2 2 @ pentograph 2 [3]
repeat 2 2 @ repeat 2 3 @ pentograph 2 []
repeat 2 2 @ repeat 2 3 @ []
[2; 2] @ [3; 3] @ []
[2; 2; 3, 3]
最后,作为一种风格偏好,我们可以在模式匹配上使用守卫,而不是 if/else 来稍微清理一下。
let rec pentograph n lst =
match lst with
| [] -> []
| x::xs when x > 1 -> repeat n x @ pentograph n xs
| _::xs -> pentograph n xs
所以我尝试在 OCaml 中编写一个相对简单的函数,它接受一个整数 n 和一个最多为 5 的整数列表,然后将所述列表中大于 1 的所有整数重复 n 次。
我已经有一个现有的函数 repeat,无论我给它什么,它都会重复 n 次
let rec repeat : int -> 'a -> 'a list =
fun n a ->
match n with
| 0 -> []
| h -> a :: repeat (h-1) a ;;
下面是名为 Pentograph 的函数的代码
let pentograph : int -> int list-> int list =
fun n letter ->
match letter with
|[] -> []
|h::t -> if h>1 then List.concat[(repeat n h);pentograph n t] else List.conca[h;pentograph n t];;
我收到以下错误:
Error: Unbound value pentograph
在尝试使用 :: 运算符时我也遇到了错误,因为我无法使用它来连接 2 个列表。
请帮我想办法解决这个问题!
编辑:如果正确答案或更优化的答案使用 map 那么请用它来回答而不是试图修复我的代码。
Ocaml 中的列表是一种带有一些语法糖的变体类型,而不是典型的用户定义的变体类型。列表可以是一个空列表 ([]
),也可以是使用 ::
运算符附加到列表上的 'a
类型的某些元素。由于这是一种递归类型,因此我们使用递归来处理它们也就不足为奇了。
也可以使用 @
运算符连接列表。
你的repeat
功能不错。我将省略显式类型并稍微重新格式化它:
let rec repeat n a =
match n with
| 0 -> []
| _ -> a :: repeat (n - 1) a
您已经定义了退出条件。如果我们要求函数重复某些内容 0
次,我们会得到一个空列表。否则,我们将 a
添加到重复函数少一次的结果的前面。第二阶段设置状态更新,使其更接近退出条件。
repeat 4 6
6 :: repeat 3 6
6 :: 6 :: repeat 2 6
6 :: 6 :: 6 :: repeat 1 6
6 :: 6 :: 6 :: 6 :: repeat 0 6
[6; 6; 6; 6]
因此,对 pentograph
函数执行相同的操作。需要多次重复,和一个列表。我们可以递归地遍历列表,所以自然退出条件是一个空列表。如果列表为空,则结果应为空列表。
let rec pentograph n lst =
match lst with
| [] -> []
否则列表将是一些值和列表的剩余部分。
let rec pentograph n lst =
match lst with
| [] -> []
| x::xs -> ...
现在我们知道x
是列表的第一个元素,所以我们可以检查它是否大于1。
let rec pentograph n lst =
match lst with
| [] -> []
| x::xs ->
if x > 1 then ...
else ...
如果它大于 1,我们会将重复工作外包给 repeat
,并将其添加到列表其余部分 运行 宁 pentograph
的前面。如果不是,我们将只 运行 列表其余部分的 pentograph
函数,忽略结果中的 x
。
let rec pentograph n lst =
match lst with
| [] -> []
| x::xs ->
if x > 1 then
repeat n x :: pentograph n xs
else
pentograph n xs
现在,让我们尝试评估一下 pentograph 2 [1; 2; 3]
。
pentograph 2 [1; 2; 3]
pentograph 2 [2; 3]
repeat 2 2 :: pentograph 2 [3]
repeat 2 2 :: repeat 2 3 :: pentograph 2 []
repeat 2 2 :: repeat 2 3 :: []
[2; 2] :: [3; 3] :: []
[[2; 2]; [3; 3]]
现在,您可能正在寻找的结果是 [2; 2; 3; 3]
,因此我们可以用列表 concatenation.
let rec pentograph n lst =
match lst with
| [] -> []
| x::xs ->
if x > 1 then
repeat n x @ pentograph n xs
else
pentograph n xs
现在:
pentograph 2 [1; 2; 3]
pentograph 2 [2; 3]
repeat 2 2 @ pentograph 2 [3]
repeat 2 2 @ repeat 2 3 @ pentograph 2 []
repeat 2 2 @ repeat 2 3 @ []
[2; 2] @ [3; 3] @ []
[2; 2; 3, 3]
最后,作为一种风格偏好,我们可以在模式匹配上使用守卫,而不是 if/else 来稍微清理一下。
let rec pentograph n lst =
match lst with
| [] -> []
| x::xs when x > 1 -> repeat n x @ pentograph n xs
| _::xs -> pentograph n xs