1️⃣ 为什么数组可以作为 Monad
在函数式编程中,Monad 的核心特征是:
- 容器类型,封装值
- bind / flatMap:接受一个返回同类型容器的函数,并将嵌套容器“平铺”
- 遵循 Monad 规律:左单位元、右单位元、结合律
数组作为容器
- 数组
[A]是一个容器,可以包含 0 或多个值 - 函数
(A) -> [B]可以返回多个值 flatMap可以将[ [B] ]平铺成[B]
结合律示例:
let a = [1, 2]
let f: (Int) -> [Int] = { [$0, $0 * 2] }
let g: (Int) -> [Int] = { [$0 - 1, $0 + 1] }
let left = a.flatMap(f).flatMap(g)
let right = a.flatMap { x in f(x).flatMap(g) }
print(left == right) // true
✅ 数组满足 Monad 特性
2️⃣ 示例:数组操作组合函数
假设我们有一些操作函数:
// 每个操作返回一个数组(可能有多个结果)
func addOne(_ x: Int) -> [Int] {
[x + 1]
}
func multiplyTwo(_ x: Int) -> [Int] {
[x * 2]
}
func duplicates(_ x: Int) -> [Int] {
[x, x] // 生成重复值
}
3️⃣ 泛型链式组合函数
func chainArrays(_ input: [Int], operations: [(Int) -> [Int]]) -> [Int] {
return operations.reduce(input) { result, op in
result.flatMap(op) // flatMap 平铺嵌套数组
}
}
4️⃣ 使用示例
let initial = [1, 2]
let operations: [(Int) -> [Int]] = [addOne, multiplyTwo, duplicates]
let finalResult = chainArrays(initial, operations: operations)
print(finalResult)
输出解释:
[1, 2]→addOne→[2, 3][2, 3]→multiplyTwo→[4, 6][4, 6]→duplicates→[4, 4, 6, 6]
✅ 每一步都是 Monad bind(flatMap) ,数组嵌套自动平铺
5️⃣ 总结
| 特性 | 数组 Monad |
|---|---|
| 容器 | [A] |
| bind / flatMap | array.flatMap { (A) -> [B] } -> [B] |
| 单位元 | 空数组 [] |
| 规律 | 左单位元、右单位元、结合律 |
| 优势 | 可组合多个操作,自动平铺结果,避免嵌套数组 |
💡 核心思想:数组可以返回多个值,flatMap 让这些多值平铺组合,天然体现 Monad 的“平铺容器、链式组合”语义。