学习笔记十六——Rust Monad从头学
🧠 零基础也能懂的 Rust Monad:逐步拆解 + 三大定律通俗讲解 + 实战技巧
📣 第一部分:Monad 是什么?
Monad 是一种“包值 + 链操作 + 保持结构”的代码模式,用来处理带上下文的值,并方便连续处理。
✅ 用人话怎么说?
你可以把 Monad 想成“装了值的容器”,它还带了一套通用的处理流程,能帮你做以下三件事:
- 包裹值:比如用户输入
5,你包装成Some(5),表示“有值”。 - 自动判断是否处理:值存在就处理,不存在就跳过。
- 统一结构,不出错:你不管怎么处理,最后结构还保持不变(比如一直是
Option<T>)。
🧩 第二部分:Monad 三大组成要素
这三样东西是判断一个类型是不是 Monad 的“标准配件”。
| 要素 | 名称 | 用通俗话解释 | Rust 中的样子 |
|---|---|---|---|
| ① 包装器 | 类型构造器 | 把值“装进盒子” | Some(x)、Ok(x)、async { x } |
| ② 起点函数 | 单位函数(unit) | 把普通值变成最简单的 Monad 容器 | Some(x)、Ok(x) |
| ③ 链接器 | 绑定函数(bind) | 如果有值就继续调用下一个操作 | .and_then(...) |
这些特性让我们可以放心大胆地“串”代码逻辑。
🔍 第三部分:什么叫“上下文”和“结构保持不变”?
| 例子 | 上下文的含义 |
|---|---|
Option<T> | 这个值可能为空(None) |
Result<T,E> | 这个操作可能失败 |
Future<T> | 这个值未来才会得到 |
✅ 举个例子:
Some(5).and_then(|x| Some(x + 1)).and_then(|y| Some(y * 2))
这里的每一步都保留了 Option 结构,不会突然变成裸值 i32。这就叫结构不变。
🧪 第四部分:三大定律彻底通俗讲清楚!
✅ 左单位律(Left Identity)
定义:
unit(x).bind(f) == f(x)
用人话说:
把值放进盒子再处理,和你直接处理这个值,没区别!
示例:
fn f(x: i32) -> Option<i32> {Some(x + 1)
}let a = Some(5).and_then(f); // 左边:unit(x).bind(f)
let b = f(5); // 右边:直接调用 f(x)assert_eq!(a, b); // 都是 Some(6)
口诀:“左边装进去再处理,和直接处理一样。”
✅ 右单位律(Right Identity)
定义:
m.bind(unit) == m
用人话说:
如果你对值“啥也不干就原样放回去”,等于什么都没做。
示例:
let x = Some("hi");
let result = x.and_then(|v| Some(v)); // 就是 unit(v)assert_eq!(result, x); // 不变
口诀:“右边原样返回,啥也没改变。”
✅ 结合律(Associativity)
定义:
m.bind(f).bind(g) == m.bind(|x| f(x).bind(g))
用人话说:
不管你是“先 f 后 g”还是“把 f 和 g 合起来一起处理”,结果一样!
示例:
fn f(x: i32) -> Option<i32> { Some(x + 1) }
fn g(x: i32) -> Option<i32> { Some(x * 2) }let m = Some(3);
let a = m.and_then(f).and_then(g);
let b = m.and_then(|x| f(x).and_then(g));assert_eq!(a, b); // 都是 Some(8)
理解要点:
f(x)是第一步g(...)是第二步- 两种写法是“逐步绑定”和“整体组合”的区别
口诀:“多步绑定能拆合,合成一起也不差。”
📘 第五部分:从例子理解 Option 是怎么应用 Monad 的
fn validate_email(email: Option<String>) -> Option<String> {email.and_then(|e| {if e.contains("@") {Some(e)} else {None}})
}
每行拆解:
Option<String>:这个邮箱可能存在也可能不存在.and_then(...):如果有值就执行闭包,否则直接 None|e| {...}:取出值e后判断是否含有@- 满足条件返回
Some(e),否则返回None
体现了什么?
- ✅ 用
Some(email)开始:unit(x) - ✅ 用
.and_then(...)处理:bind - ✅ 最后返回的仍是
Option<String>:结构不变
🔧 第六部分:.map() vs .and_then() 有啥区别?
| 方法 | 用法说明 | 示例 |
|---|---|---|
.map() | 对值做处理,结果仍在容器内 | `Some(2).map( |
.and_then() | 处理后返回另一个容器(嵌套) | `Some(2).and_then( |
.map() 相当于你“只动里面的值”,.and_then() 是你“根据值决定接下去是否继续”。
🔁 第七部分:组合多个操作 - 用 Monad 串业务逻辑
fn parse_id(s: &str) -> Option<i32> {s.parse().ok()
}fn check_id(id: i32) -> Option<i32> {if id > 0 { Some(id) } else { None }
}fn query_user(id: i32) -> Option<String> {Some(format!("用户{}", id))
}let user = Some("42").and_then(parse_id).and_then(check_id).and_then(query_user);
用人话解释:
如果字符串能成功转成数字、这个数字大于 0、还能找到用户,就返回用户名;否则中途停止。
这就是典型的:组合多个失败可能的操作
🧾 第八部分:总结表格
| 类型 | 类型构造器 | unit函数 | bind函数 | 上下文解释 |
|---|---|---|---|---|
| Option | Some(x) | Some(x) | and_then | 可能没有值 |
| Result | Ok(x)/Err(e) | Ok(x) | and_then | 成功/失败状态 |
| Future | async { x } | async | await / then | 值尚未获得 |
✅ 结语
掌握 Monad 不是为了炫技,而是为了安全、优雅、高复用地处理流程和异常。
如果你能理解这三句话:
- 我可以从值开始(左单位律)
- 我可以随时停下不处理(右单位律)
- 我可以拆写也能合写(结合律)
相关文章:
学习笔记十六——Rust Monad从头学
🧠 零基础也能懂的 Rust Monad:逐步拆解 三大定律通俗讲解 实战技巧 📣 第一部分:Monad 是什么? Monad 是一种“包值 链操作 保持结构”的代码模式,用来处理带上下文的值,并方便连续处理。 …...
Linux:显示 -bash-4.2$ 问题(CentOS 7)
文章目录 一、原因二、错误示例三、解决办法 一、原因 在 CentOS 7 系统中,如果你看到命令行提示符显示为 -bash-4.2$,一般是 Bash shell 正在运行,并且它没有找到用户的个人配置文件,或者这些文件有问题而未能成功加载。这个提示…...
linux共享内存通信
基础共享内存通信示例 以下示例展示生产者-消费者模型,使用共享内存传递数据: 生产者程序(producer.c) #include <sys/ipc.h> #include <sys/shm.h> #include <stdio.h> #include <string.h>#define S…...
视频监控EasyCVR视频汇聚平台接入海康监控摄像头如何配置http监听功能?
一、方案概述 本方案主要通过EasyCVR视频管理平台,实现报警信息的高效传输与实时监控。海康监控设备能通过HTTP协议将报警信息发送至指定的目的IP或域名,而EasyCVR平台则可以接收并处理这些报警信息,同时提供丰富的监控与管理功能࿰…...
代码随想录算法训练营第二十天
LeetCode题目: 39. 组合总和40. 组合总和 II131. 分割回文串2176. 统计数组中相等且可以被整除的数对(每日一题) 其他: 今日总结 往期打卡 39. 组合总和 跳转: 39. 组合总和 学习: 代码随想录公开讲解 问题: 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 targ…...
DAY09:【pytorch】nn网络层
1、卷积层 1.1 Convolution 1.1.1 卷积操作 卷积运算:卷积核在输入信号(图像)上滑动,相应位置上进行乘加卷积核:又称为滤波器、过滤器,可认为是某种模式、某种特征 1.1.2 卷积维度 一般情况下…...
大模型面试题
分布式训练相关面试题解答 什么是分布式训练? 分布式训练是一种利用多个计算节点(如多个 GPU 或多个机器)协同工作来加速训练机器学习模型的方法。它通过将训练任务分配给多个计算资源并行执行,以减少训练时间和处理大规模数据。…...
跟康师傅学Java-面向对象(基础)
跟康师傅学Java-面向对象(基础) 学习面向对象内容的三条主线(非官方) ①Java类及类的成员:(重点)属性、方法、构造器;(熟悉)代码块、内部类 ②面向对象的特征:封装、继承、多态、(抽象) ③其他关键字的使用:this、super、package、import、static、final、inte…...
2000-2017年各省国有经济煤气生产和供应业固定资产投资数据
2000-2017年各省国有经济煤气生产和供应业固定资产投资数据 1、时间:2000-2017年 2、来源:国家统计局、能源年鉴 3、指标:行政区划代码、城市、年份、国有经济煤气生产和供应业固定资产投资 4、范围:31省 5、指标说明&#x…...
线性代数 | 知识点整理 Ref 3
注:本文为 “线性代数 | 知识点整理” 相关文章合辑。 因 csdn 篇幅合并超限分篇连载,本篇为 Ref 3。 略作重排,未整理去重。 图片清晰度限于引文原状。 如有内容异常,请看原文。 《线性代数》总复习要点、公式、重要结论与重点释…...
从原理到实践:NFS复杂故障处理方法论
#作者:孙德新 文章目录 一、nfs使用概述二、疑难故障现象描述三、原理分析四、解决方案五、优化服务器资源配置:六、故障案例总结七、故障预防建议八、nfs优化方法 一、nfs使用概述 NFS(Network File System)是一种分布式文件系…...
网络层IP协议知识大梳理
全是通俗易懂的讲解,如果你本节之前的知识都掌握清楚,那就速速来看我的IP协议笔记吧~ 自己写自己的八股!让未来的自己看懂! (全文手敲,受益良多) 网路基础3 网路层 TCP并没有把数据发到网路…...
【Web前端技术】第二节—HTML标签(上)
hello!好久不见—— 做出一个属于自己的网站! 云边有个稻草人-个人主页 Web前端技术—本篇文章所属专栏 目录 一、HTML 语法规范 1.1 基本语法概述 1.2 标签关系 二、HTML 基本结构标签 2.1 第一个 HTML 网页 2.2 基本结构标签总结 三、网页开发…...
1.Axum 与 Tokio:异步编程的完美结合
摘要 深入解析 Axum 核心架构与 Tokio 异步运行时的集成,掌握关键原理与实践技巧。 一、引言 在当今的软件开发领域,高并发和高性能是衡量一个系统优劣的重要指标。对于 Web 服务器而言,能够高效地处理大量并发请求是至关重要的。Rust 语言…...
08软件测试需求分析案例-删除用户
删除用户是后台管理菜单的一个功能模块,只有admin才有删除用户的权限。不可删除admin。 1.1 通读文档 通读需求规格说明书是提取信息,提出问题,输出具有逻辑、规则、流程的业务步骤。 信息:此功能应为用户提供确认删除的功能。…...
SDL基础
SDL SDL(Simple DirectMedia Layer)是一个开源的跨平台多媒体开发库,主要用于开发需要图形、音频和输入设备支持的应用程序。它使用C语言编写,提供了简单易用的API,**能够帮助开发者快速实现跨平台的多媒体功能。**SD…...
十三种通信接口芯片——《器件手册--通信接口芯片》
目录 通信接口芯片 简述 基本功能 常见类型 应用场景 详尽阐述 1 RS485/RS422芯片 1. RS485和RS422标准 2. 芯片功能 3. 典型芯片及特点 4. 应用场景 5. 设计注意事项 6. 选型建议 2 RS232芯片 1. RS232标准 2. 芯片功能 3. 典型芯片及特点 4. 应用场景 5. 设计注意事项 6…...
反转一个字符串
用数组栈实现 void Reverse(char *C, int len) {top -1;for(int i 0; i < len; i){push(C[i]);}for(int i 0; i < len; i){C[i] Top();pop();} } 全部函数 #include <stdio.h> #include <stdlib.h> #include <string.h>#define MAX_SIZE 101int …...
从GPT到Gemini 大模型进化史
从GPT到Gemini:大模型进化史 在过去的几年里,人工智能领域经历了翻天覆地的变化,其中最引人注目的莫过于大规模语言模型的发展。从最初的GPT系列到最近的Gemini,这些模型不仅在技术上取得了重大突破,还在实际应用中展…...
【限流算法】计数器、漏桶、令牌桶算法
1 计数器 使用计数器实现限流,可限制在指定时间间隔内请求数小于阈值的情况,但存在临界问题。如图1-17所示,假设每分钟系统限流500个请求,在XX:00:59时刻系统接收到500个请求,在XX:01:00时刻系统又接收到500个请求&am…...
秘密任务 2.0:如何利用 WebSockets + DTOs 设计实时操作
在之前的文章中,我们探讨了为什么 DTO 是提升 API 效率和安全性的秘密武器。现在,我们进入了一个全新的场景——我们将深入探讨如何通过 WebSockets DTOs 实现实时操作! Agent X 正在进行一项高风险的卧底任务。突然,总部更新了…...
RAII 技术详解
1. 核心概念 定义:RAII(Resource Acquisition Is Initialization,资源获取即初始化)是 C 中通过对象生命周期管理资源的核心机制,核心思想是将资源的获取与对象构造绑定、资源释放与对象析构绑定,确…...
Windows快速切换屏幕/桌面
windows自带的切屏 需要winctrl 小键盘左右键 但是! Windows使用还是键盘加鼠标舒服! 教程 安装autohotkey 代码 ~LWin & LButton::{SendInput "^#{Left}" ; 发送 Win Ctrl Left (切换到左侧虚拟桌面) } ; 使用花括号包裹命令&a…...
SpringAI+DeepSeek大模型应用开发——3 SpringAI简介
SpringAI整合了全球(主要是国外)的大多数大模型,而且对于大模型开发的三种技术架构都有比较好的封装和支持,开发起来非常方便; 不同的模型能够接收的输入类型、输出类型不一定相同。SpringAI根据模型的输入和输出类型…...
使用 Function 来编写策略模式:优雅而高效的设计模式实践
引言:为什么选择策略模式? 策略模式(Strategy Pattern)是行为设计模式中的经典之一,它允许我们定义一系列的算法或操作,并使得它们可以互换使用。策略模式的关键思想是将算法的实现与使用它们的上下文分离…...
Java字符串处理
Java字符串处理全解析:String、StringBuilder与StringBuffer 一、String类基础 1. String的本质 不可变对象:Java中的String对象一旦创建就不能修改底层实现:基于private final char value[]字符数组字符串池:JVM维护的特殊存储…...
JS实现RSA加密
目录 目标 环境 实现RSA加解密 计算RSA加密允许的最大字节长度 目标 使用JS实现RSA加密解密。计算RSA加密允许的最大字节长度。 环境 node-rsa 实现RSA加解密 const NodeRSA require(node-rsa);function getKey() {const keyLength512// 创建 RSA 密钥对const key new …...
MySQL GTID集合运算函数总结
MySQL GTID 有一些运算函数可以帮助我们在运维工作中提高运维效率。 1 GTID内置函数 MySQL 包含GTID_SUBSET、GTID_SUBTRACT、WAIT_FOR_EXECUTED_GTID_SET、WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS 4个内置函数,用于GTID集合的基本运算。 1.1 GTID_SUBSET(set1,set2) …...
从“链主”到“全链”:供应链数字化转型的底层逻辑
1. 制造业与供应链数字化转型的必然性 1.1. 核心概念与战略重要性 制造业的数字化转型,是利用新一代数字技术(如工业互联网、人工智能、大数据、云计算、边缘计算等)对制造业的整体价值链进行根本性重塑的过程。这不仅涉及技术的应用&#…...
学习笔记十五——rust柯里化,看不懂 `fn add(x) -> impl Fn(y)` 的同学点进来!
🧠 Rust 柯里化从零讲透:看不懂 fn add(x) -> impl Fn(y) 的同学点进来! 🍔 一、什么是柯里化?先用一个超好懂的生活比喻 假设你在点一个汉堡: 你说:我要点一个鸡腿汉堡! 店员…...
