【发布时间】:2017-03-28 15:48:56
【问题描述】:
我正在尝试结合 Writer 和 State(通过 Lens)。我很确定我需要 monad 转换器,但我很难弄清楚如何使用 T 版本以及如何正确构建它。
现在我有一些模型(简化):
case class Schedule(due: LocalDate)
case class Task(title: String, schedule: Schedule)
为每个字段定义的镜头,titleL、scheduleL 和 dueL。
我的 Writer type Logger[A] = Writer[Vector[String], A] 的类型别名
还有一些修改我的模型的功能:
def changeTitle(title: String): Task => Logger[Task] = { t: Task =>
for {
a <- titleL.set(t, title).point[Logger]
_ <- ("Title changed to " + a.title).point[Vector].tell whenM (a.title != t.title)
} yield a
}
def changeDue(date: LocalDate): Schedule => Logger[Schedule] = { s: Schedule =>
for {
a <- dueL.set(s, date).point[Logger]
_ <- ("Due changed to " + a.due).point[Vector].tell whenM (a.due != s.due)
} yield a
}
但是现在我不确定如何将 lens 或 state 方法与最后一个函数一起使用。
我希望能够做一些看起来像这样的事情:
def reschedule(date: LocalDate): Task => Logger[Task] = { t: Task =>
(for {
a <- scheduleL %= reschedule(date)
_ <- ("Reschedule: " + a.schedule).point[Vector].tell whenM (a.schedule != t.schedule)
} yield a) exec t
}
我应该如何处理这个问题?我在单子变压器的正确轨道上吗?还有什么我可能遗漏的已经处理了我的案子的事情吗?
编辑:
我得到了这样的东西,它适用于那个用例,但我想要一些能更好地与 State 集成以用于更复杂的东西:
def reschedule(date: LocalDate): Task => Logger[Task] = { t: Task =>
for {
sa <- scheduleL.get(t).point[Logger]
sb <- changeDue(date)(sa)
a <- scheduleL.set(t, sb).point[Logger]
_ <- ("Reschedule: " + a.schedule).point[Vector].tell whenM (a.schedule != t.schedule)
} yield a
}
【问题讨论】: