深入理解基础单子与单子变换器
立即解锁
发布时间: 2025-08-19 00:05:39 阅读量: 1 订阅数: 3 

Scala 2.13编程实战与进阶
# 深入理解基础单子与单子变换器
## 1. 基础单子介绍
### 1.1 Reader 单子
Reader 单子与 State 单子类似,用于处理外部状态。State 单子表示外部状态,可能会被修改;而 Reader 单子接受外部上下文,并将其原封不动地传递给队列中的每个计算,可访问只读系统属性,常被用作依赖注入机制。
#### 定义
```scala
final case class Reader[R, A](run: R => A) {
def compose[B](f: A => Reader[R, B]): Reader[R, B] =
Reader { r: R =>
f(run(r)).run(r)
}
}
object Reader {
def apply[R, A](a: => A): Reader[R, A] = Reader(_ => a)
}
```
#### 单子定义
```scala
implicit def readerMonad[R] = new Monad[Reader[R, ?]] {
override def unit[A](a: => A): Reader[R, A] = Reader(a)
override def flatMap[A, B](a: Reader[R, A])(f: A => Reader[R, B]):
Reader[R, B] = a.compose(f)
}
```
#### 示例:船的移动
假设存在船速和转向角度的限制,我们可以使用 Reader 单子来应用这些限制。
```scala
final case class Limits(speed: Float, angle: Double)
type ReaderLimits[A] = ch09.Reader[Limits, A]
def go(speed: Float, time: Float)(boat: Boat): ReaderLimits[Boat] =
ch09.Reader(limits => {
val lowSpeed = Math.min(speed, limits.speed)
boat.go(lowSpeed, time)
})
def turn(angle: Double)(boat: Boat): ReaderLimits[Boat] =
ch09.Reader(limits => {
val smallAngle = Math.min(angle, limits.angle)
boat.turn(smallAngle)
})
```
运行示例:
```scala
import Monad.readerMonad
import Boat._
println(move(go, turn)(ch09.Reader(boat)).run(Limits(10f, 0.1)))
```
### 1.2 Writer 单子
Writer 单子主要用于在计算过程中记录日志,它会在计算之间传递日志信息。日志类型通常选择追加操作开销较小的结构,如 Vector 或 List。
#### 定义
```scala
import ch07._
final case class Writer[W: Monoid, A](run: (A, W)) {
def compose[B](f: A => Writer[W, B]): Writer[W, B] = Writer {
val (a, w) = run
val (b, ww) = f(a).run
val www = implicitly[Monoid[W]].op(w, ww)
(b, www)
}
}
object Writer {
def apply[W: Monoid, A](a: => A): Writer[W, A] = Writer((a,
implicitly[Monoid[W]].identity))
}
```
#### 单子定义
```scala
implicit def writerMonad[W : Monoid] = new Monad[Writer[W, ?]] {
override def unit[A](a: => A): Writer[W, A] = Writer(a)
override def flatMap[A, B](a: Writer[W, A])(f: A => Writer[W, B]):
Writer[W, B] = a.compose(f)
}
```
#### 示例:记录船的位置
假设规定需要记录船的每次移动位置,我们可以使用 Writer 单子来实现。
```scala
type WriterTracking[A] = Writer[Vector[(Double, Double)], A]
def go(speed: Float, time: Float)(boat: Boat): WriterTracking[Boat] = new
WriterTracking((boat.go(speed, time), Vector(boat.position)))
implicit def vectorMonoid[A]: Monad[Vector[A]] =
new Monad[Vector[A]] {
override def identity: Vector[A] = Vector.empty[A]
override def op(l: Vector[A], r: Vector[A]): Vector[A] = l ++ r
}
```
运行示例:
```scala
import Monad.writerMonad
import Boat.{move, boat, turn}
println(move(go, turn[WriterTracking])(Writer(boat)).run)
```
### 1.3 不同单子的作用总结
| 单子类型 | 作用 |
| ---- | ---- |
| Id | 直接组合计算 |
| Option | 若某一步无结果,则停止计算 |
| Try 和 Either | 与 Option 语义类似,但可指定无结果的含义 |
| Writer | 提供追加日志功能
0
0
复制全文


