【PL理论深化】(8) Ocaml 语言:元组和列表 | 访问元组中的元素 | 列表中的 head 和 tail | 基本列表操作符

  • 💬 写在前面:本章我们将探讨 OCaml  中的元组(tuple)和列表(list),它们是函数式编程语言中最常用的数据结构。
  • 目录

    0x00 元组(Tuple)

    0x01 访问元组中的元素

    0x02 列表(list)

    0x03 列表的 head 和 tail

    0x04 基本列表操作符


0x00 元组(Tuple)

元组 (tuple) 是值的 有序集合 (in-order set) ,例如:

元组 (1, "one") 包含了一个整数和一个字符串,其类型可以表示为 int * string

元组 (2, "two", true) 包含了一个整数, 一个字符串和一个布尔值,其类型为 int * string * bool

# let x = (1, "one");;
val x : int * string = (1, "one")
# let y = (2, "two", true);;
val y : int * string * bool = (2, "two", true)

0x01 访问元组中的元素

要访问元组的每个元素,可以使用模式匹配。

例如,可以定义如下函数 fstsnd,用于获取由两个元素组成的元组的第一个和第二个元素。

# let fst p = match p with (x,_) -> x;;
val fst : ’a * ’b -> ’a = <fun>
# let snd p = match p with (_,x) -> x;;
val snd : ’a * ’b -> ’b = <fun>

或者可以直接在函数的参数中使用元组模式,如下所示:

# let fst (x,_) = x;;
val fst : ’a * ’b -> ’a = <fun>
# let snd (_,x) = x;;
val snd : ’a * ’b -> ’b = <fun>

类型 'a * 'b -> 'a 表示函数 fst 接受一个由任意类型 {}'a 和 {}'b 组成的元组作为输入,

并返回类型为 {}'a 的值。通过函数的类型,我们可以推断出函数的大致作用。

不仅在函数参数中,还可以在 let 表达式中使用元组模式。例如,看下面的代码:

# let p = (1, true);;
val p : int * bool = (1, true)
# let (x,y) = p;;
val x : int = 1
val y : bool = true

p 代表元组 (1, true),并将其分解为 x 和 y

0x02 列表(list)

列表 (List) 是具有相同类型的元素序列。

例如, 由数字 1, 2, 3 组成的列表表示为 [1,2,3] ,其类型是 int list

# [1; 2; 3];;
- : int list = [1; 2; 3]

在 OCaml 中,列表中的每个元素用分号 ; 分隔。将每个元素用逗号 , 

分隔的列表 [1, 2, 3] 被识别为包含元组 (1,2,3) 作为其元素的列表 [(1,2,3)] ,

因此需要注意这一点:

# [1,2,3];;
- : (int * int * int) list = [(1, 2, 3)]
# [(1,2,3)];;
- : (int * int * int) list = [(1, 2, 3)]

空列表在 OCaml 中用 [\, ]  表示,其类型是 'a list,表示多态类型:

# [];;
- : ’a list = []

在 OCaml 中,列表的所有元素必须是相同的类型。

例如,[1;true] 在 OCaml 中不是一个列表:

# [1; true];;
Error: This expression has type bool but an expression
was expected of type int

这种限制也源于静态类型系统。

例如,在具有动态类型系统 (如 Python) 的语言中,列表可以包含不同类型的值。

另外,列表是有序元素的序列。因此,下面这两个列表是不同的列表。

# [1;2;3] = [2;3;1];;
- : bool = false

0x03 列表的 head 和 tail

列表的第一个元素称为 head,除第一个元素外剩余的列表称为 tail,即头和尾。

举个例子,对于列表:

 [1; 2;3;4;5;6;7;8] \in \left \langle list \right \rangle

头是 1,尾是 2,3,4,5,6,7,8

一般来说,对于类型为 t 的列表,头的类型是 t,尾的类型是 t list 

列表的元素可以是任意类型的值,当然,每个元素的类型必须相同。

# [1;2;3;4;5];;
- : int list = [1; 2; 3; 4; 5]
# ["OCaml"; "Java"; "C"];;
- : string list = ["OCaml"; "Java"; "C"]
# [(1,"one"); (2,"two"); (3,"three")];;
- : (int * string) list =[(1, "one"); (2, "two"); (3, "three")]
# [[1;2;3];[2;3;4];[4;5;6]];;
- : int list list = [[1; 2; 3]; [2; 3; 4]; [4; 5; 6]]

最后一个例子是整数列表的列表 (int list list) 。

在这种情况下, 每个元素对应的列表可以有不同的长度。

# [[1;2;3]; [4]; []];;
- : int list list = [[1; 2; 3]; [4]; []]

列表 [1; 2; 3] 和 [4],尽管长度不同,都是整数列表;

空列表 [\, ] 是多态类型,因此也可以是整数列表。

0x04 基本列表操作符

首先是 ::(读作 cons),它可以在列表的最前面添加一个元素,从而创建一个新的列表。

# 1::[2;3];;
- : int list = [1; 2; 3]
# 1::2::3::[];;
- : int list = [1; 2; 3]

将两个列表连接在一起时,使用 @ (读作 append)。

# [1; 2] @ [3; 4; 5];;
- : int list = [1; 2; 3; 4; 5]

在编写处理列表的函数时,模式匹配经常被使用。

例如,我们可以定义函数 hd 和 tl 来获取列表的头部和尾部。

# let hd l =match l with| [] -> raise (Failure "hd is undefined")| a::b -> a;;
val hd : ’a list -> ’a = <fun>
# let tl l =match l with| [] -> raise (Failure "tl is undefined")| a::b -> b;;
val tl : ’a list -> ’a list = <fun>
# hd [1;2;3];;
- : int = 1
# tl [1;2;3];;
- : int list = [2; 3]

列表的头部和尾部对于空列表是未定义的。

如果列表 l 不是空列表,则可以将其分解为头部 a 和尾部 b

其中 hd 返回 atl 返回 b(如果列表 l 是单元素列表,则尾部 tl 是空列表)。

请注意,在上述定义中,这两个函数的返回类型是不同的。

如果省略异常处理,也可以简单地定义如下:

# let hd (a::b) = a;;
Warning 8: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
[]
val hd : ’a list -> ’a = <fun>
# let tl (a::b) = b;;
Warning 8: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
[]
val tl : ’a list -> ’a list = <fun>

在这种情况下,OCaml 提醒我们函数 hd 和 tl 没有考虑空列表的情况。

虽然这些警告信息不是编译错误,但可能在运行时引发未处理的异常,

建议事先处理所有可能的情况。举个例子,我们可以尝试编写一个函数来计算列表的长度:

# let rec length l =match l with[] -> 0|h::t -> 1 + length t;;
val length : ’a list -> int = <fun>
# length [1;2;3];;
- : int = 3

给定的列表 l 如果是空列表,则定义其长度为 0。

如果不为空,则可以将列表 l 分为头部 h 和尾部 t

此时列表 l 的长度应该等于尾部 t 的长度加 1。

根据上述定义,由于头部 h 没有被使用,可以用下划线 (_) 来表示省略:

let rec length l =match l with[] -> 0|_::t -> 1 + length t

📌 [ 笔者 ]   王亦优
📃 [ 更新 ]   2024.6.28
❌ [ 勘误 ]   /* 暂无 */
📜 [ 声明 ]   由于作者水平有限,本文有错误和不准确之处在所难免,本人也很想知道这些错误,恳望读者批评指正!

📜 参考资料 

- R. Neapolitan, Foundations of Algorithms (5th ed.), Jones & Bartlett, 2015.

- T. Cormen《算法导论》(第三版),麻省理工学院出版社,2009年。

- T. Roughgarden, Algorithms Illuminated, Part 1~3, Soundlikeyourself Publishing, 2018.

- J. Kleinberg&E. Tardos, Algorithm Design, Addison Wesley, 2005.

- R. Sedgewick&K. Wayne,《算法》(第四版),Addison-Wesley,2011

- S. Dasgupta,《算法》,McGraw-Hill教育出版社,2006。

- S. Baase&A. Van Gelder, Computer Algorithms: 设计与分析简介》,Addison Wesley,2000。

- E. Horowitz,《C语言中的数据结构基础》,计算机科学出版社,1993

- S. Skiena, The Algorithm Design Manual (2nd ed.), Springer, 2008.

- A. Aho, J. Hopcroft, and J. Ullman, Design and Analysis of Algorithms, Addison-Wesley, 1974.

- M. Weiss, Data Structure and Algorithm Analysis in C (2nd ed.), Pearson, 1997.

- A. Levitin, Introduction to the Design and Analysis of Algorithms, Addison Wesley, 2003. - A. Aho, J. Hopcroft, and J. Ullman, Data Structures and Algorithms, Addison-Wesley, 1983.

- E. Horowitz, S. Sahni and S. Rajasekaran, Computer Algorithms/C++, Computer Science Press, 1997.

- R. Sedgewick, Algorithms in C: 第1-4部分(第三版),Addison-Wesley,1998

- R. Sedgewick,《C语言中的算法》。第5部分(第3版),Addison-Wesley,2002

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/862142.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

沉淀强化镍基合金660大螺丝的物理性能

沉淀强化镍基合金660大螺丝&#xff0c;是一种高性能的工程材料&#xff0c;其在极端环境中展现了优异的稳定性和耐用性。以下&#xff0c;我们将深入解析其主要的物理性能。 首先&#xff0c;该合金螺丝的密度为7.99g/cm&#xff0c;这意味着它具有较高的质量密度&#xff0c;…

APM Profile 在系统可观测体系中的应用

引言 应用程序性能分析&#xff08;Application Performance Management&#xff0c;APM&#xff09;是一个广泛的概念&#xff0c;涉及应用程序运行时各种性能指标的监测、诊断和优化。在可观测体系建设中&#xff0c;APM 是保障系统业务运行性能的关键技术&#xff0c;确保用…

Tomcat WEB站点部署

目录 1、使用war包部署web站点 2、自定义默认网站目录 3、部署开源站点&#xff08;jspgou商城&#xff09; 对主机192.168.226.22操作 对主机192.168.226.20操作 上线的代码有两种方式&#xff1a; 第一种方式是直接将程序目录放在webapps目录下面&#xff0c;这种方式…

多协议网关BL110钡铼6路RS485转MQTT协议云网关

在工业自动化的现代化进程中&#xff0c;物联网技术的应用日益广泛&#xff0c;特别是工业物联网网关作为连接传感器、控制器和云端平台的关键枢纽&#xff0c;发挥着至关重要的作用。BL110钡铼多协议网关作为一款专为工业环境设计的先进设备&#xff0c;不仅支持多种下行采集协…

【代码随想录】【算法训练营】【第51天】 [115]不同的子序列 [583]两个字符串的删除操作 [72]编辑距离

前言 思路及算法思维&#xff0c;指路 代码随想录。 题目来自 LeetCode。 day 51&#xff0c;周四&#xff0c;又是不能坚持的一天~ 题目详情 [115] 不同的子序列 题目描述 115 不同的子序列 解题思路 前提&#xff1a; 思路&#xff1a; 重点&#xff1a; 代码实现 …

windows下修改Jar包内容的两种方式

windows下修改Jar包内容的两种方式 背景第一种&#xff1a;解压工具第二种&#xff1a;Jar命令附Jar命令用法基本用法常见选项示例1&#xff1a;创建一个简单的 JAR 文件示例2&#xff1a;创建包含清单文件的 JAR 文件示例3&#xff1a;列出 JAR 文件的内容示例4&#xff1a;提…

数据库物理结构设计-定义数据库模式结构(概念模式、用户外模式、内模式)、定义数据库、物理结构设计策略

一、引言 如何基于具体的DBMS产品&#xff0c;为数据库逻辑结构设计的结果&#xff0c;即关系数据库模式&#xff0c;制定适合应用要求的物理结构 1、在设计数据库物理结构前&#xff0c;数据库设计人员首先 要充分了解所用的DBMS产品的功能、性能和特点&#xff0c;包括提供…

慧科新闻搜索研究数据库的使用指南及个人获取途径

《慧科新闻搜索研究数据库》WiseSearch由慧科讯业有限公司出品。WiseSearch是具有新闻搜索/浏览、对比分析等功能的一站式新闻搜索平台&#xff1b;内容包括1200种报刊和8000 网站的新闻资讯&#xff0c;平面媒体涵盖全国综合大报、党委机关报、都市报、行业报刊媒体&#xff0…

算法08 广/宽度优先搜索及相关问题详解

这是《C算法宝典》算法篇的第08节文章啦~ 如果你之前没有太多C基础&#xff0c;请点击&#x1f449;专栏&#xff1a;C语法入门&#xff0c;如果你C语法基础已经炉火纯青&#xff0c;则可以进阶算法&#x1f449;专栏&#xff1a;算法知识和数据结构&#x1f449;专栏&#xff…

SKYDROID-C12—— 让美景近在眼前

C12是一款小型高清双光吊舱&#xff0c;使用新一代影像芯片&#xff0c;搭配高清无畸变摄像头&#xff0c;有效像素达到500万&#xff0c;拥有强悍的2K视频录制和拍照能力&#xff0c;支持数字变倍&#xff0c;随时随地捕捉清晰的图像&#xff0c;让远处美景近在眼前。

mysql 提取拼音时一个重复字导致的错误

在提取拼音时&#xff0c;一直报错&#xff0c;提示&#xff1a;Result consisted of more than one row 最后发现是礼这个字导致的&#xff0c;发现有两个写法不同&#xff0c;但是mysql识别为同一个字导致的

el-upload+python fastAPI实现上传文件

el-upload通过action指定后端接口&#xff0c;并通过name指定传输的文件包裹在什么变量名中 <el-uploadclass"upload-demo"dragaction"https://ai.zscampus.com/toy/upload"multiplename"fileList":limit"10"accept".xlsx, .x…

高中数学:不等式-常见题型解题技巧

一、“1”的代换 练习 例题1 例题2 解 二、基本不等式中的“变形” 就是&#xff0c;一般情况下&#xff0c;我们在题目中&#xff0c;是不能够直接使用基本不等式进行求解的。 而是要对条件等式进行变形&#xff0c;满足基本不等式的使用条件 练习 例题1 解析 两边同…

一个最简单的MySQL事务模拟测试

这里只是简单写了一个转账的小事务&#xff0c;模拟一下事务的过程 代码&#xff1a; 初始数据&#xff1a; 当你关闭自动提交 并且开启一个事务执行了下面的更新语句 但是没有提交时&#xff1a; 此时虽然你运行查询语句会发现他的值发生了变化 &#xff0c;但是当你运行回滚…

鸿蒙开发HarmonyOS NEXT (一) 入门

最近总听见大家讨论鸿蒙&#xff0c;前端转型的好方向&#xff1f;先入门学习下 目前官方版本和文档持续更新中 一、开发环境 提示&#xff1a;要占用的空间比较多&#xff0c;建议安装在剩余空间多的盘 1、下载&#xff1a;官网最新工具 - 下载中心 - 华为开发者联盟 (huaw…

放烟花短视频素材去哪里找?去哪里下载?烟花素材网分享

在当代社会&#xff0c;短视频凭借其独有的魅力成为大众传递情感、记录生活、分享快乐的新兴方式。特别是在庆祝节日和特殊时刻时&#xff0c;烟花的绚丽效果常常被用来吸引观众的目光&#xff0c;成为视频作品中的亮点。然而&#xff0c;对于短视频制作者来说&#xff0c;寻找…

初探 YOLOv8(训练参数解析)

文章目录 1、前言2、Backbone网络3、YOLOv8模型训练代码3.1、模型大小选择3.2、训练参数设置 4、训练参数说明5、目标检测系列文章 1、前言 YOLO 因为性能强大、消耗算力较少&#xff0c;一直以来都是实时目标检测领域的主要范式。该框架被广泛用于各种实际应用&#xff0c;包…

探索音频创作的无限可能——Studio One 5 软件深度解析

Studio One 5 是一款功能强大且备受赞誉的音频制作软件&#xff0c;无论是专业音乐制作人还是业余爱好者&#xff0c;都能在其中找到满足自己需求的强大功能。 对于 Mac 和 Windows 用户来说&#xff0c;Studio One 5 提供了一个直观且友好的操作界面。其简洁明了的布局让用户…

Windows的内核对象

内核对象句柄特定于进程。 也就是说,进程必须创建 对象或打开现有对象以获取内核对象句柄。 内核句柄上的每个进程限制为 2^24。 但是,句柄存储在分页池中,因此可以创建的实际句柄数取决于可用内存。 可以在 32 位 Windows 上创建的句柄数明显低于 2^24。 任何进程都可以为…

Haproxy负载均衡集群

一、HAProxy介绍 HAProxy是法国开发者威利塔罗(Willy Tarreau)在2000年使用C语言开发的一个开源软件&#xff0c;是一款具备高并发(一万以上)、高性能的TCP和HTTP负载均衡器&#xff0c;支持基于cookie的持久性&#xff0c;自动故障切换&#xff0c;支持正则表达式及web状态统…