ocaml - 将一个函数的列表连接到 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];;
我收到以下错误:
错误:未绑定的值五线谱
在尝试使用 :: 运算符时,我也收到一个错误,因为我无法使用它来连接 2 个列表。
请帮我找出解决这个问题的方法!
编辑:如果正确答案或更优答案使用地图,那么请回答,而不是尝试修复我的代码。
解决方案
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]
替换列表构造。
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
推荐阅读
- python - 如何拆分列元素并用python数据框中的其他列值替换?
- python - 在 Cmder/ConEmu 与代码中运行 python 文件
- vue.js - 在 vuex 中使用 vue.js (v3) 插件
- python - Django 表单未显示
- jaas - ActiveMQ Artemis:自定义登录模块从 2.17.0 开始不起作用
- node.js - 有什么方法可以更新集合单值记录并保留旧数据吗?
- mysql - 如何在 mySQL 中的组内进行排序(在 workBench 中而不是在 NodeJS 中工作)
- git - Git 使用 yaml 文件将外部 github 存储库克隆到 Azure Devops 中的本地代理
- python - 尝试选择下拉菜单选项时出现错误“消息:过时的元素引用:元素未附加到页面文档”
- python - 选择包含最有效值的数据框列