我正在围绕国家单元包围我的头。简单的例子很容易理解。我现在正转向一个真实世界的情况,即域对象是复合的。例如,下面的域对象(他们没有多大意义,只是纯粹的例子):斯卡拉州立单元 - 结合不同的州立类型
case class Master(workers: Map[String, Worker])
case class Worker(elapsed: Long, result: Vector[String])
case class Message(workerId: String, work: String, elapsed: Long)
考虑Worker
为S
类型State[S, +A]
单子它很容易写几个组合子这样的:
type WorkerState[+A] = State[Worker, A]
def update(message: Message): WorkerState[Unit] = State.modify { w =>
w.copy(elapsed = w.elapsed + message.elapsed,
result = w.result :+ message.work)
}
def getWork: WorkerState[Vector[String]] = State { w => (w.result, w) }
def getElapsed: WorkerState[Long] = State { w => (w.elapsed, w) }
def updateAndGetElapsed(message: Message): WorkerState[Long] = for {
_ <- update(message)
elapsed <- getElapsed
} yield elapsed
// etc.
将这些与Master
状态组合器结合的惯用方法是什么?例如
type MasterState[+A] = State[Master, A]
def updateAndGetElapsedTime(message: Message): MasterState[Option[Long]]
我可以像这样实现的:
def updateAndGetElapsedTime(message: Message): MasterState[Option[Long]] =
State { m =>
m.workers.get(message.workerId) match {
case None => (None, m)
case Some(w) =>
val (t, newW) = updateAndGetElapsed(message).run(w)
(Some(t), m.copy(m.workers.updated(message.workerId, newW))
}
}
我不喜欢的是,我必须手动运行的最后一个变压器内部的状态单子。我的真实世界的例子有一点涉及。采用这种方法很快就会变得混乱。
是否有更习惯的方式来运行这种增量更新?
不错的问题!你是否指的是像'scalaz'这样的具体'State'实现? – Odomontois
这绝对是'LensT'用法的好例子,迫不及待地想要看一些专家的回答。 – Odomontois