Scalaz:结合作家和国家(和/或镜头)
发布时间:2020-12-16 19:23:46 所属栏目:安全 来源:网络整理
导读:我正在尝试将Writer和State(通过镜头)结合起来.我很确定我需要monad变换器,但我很难弄清楚如何使用T版本以及如何正确构建它. 现在我有一些模型(简化): case class Schedule(due: LocalDate)case class Task(title: String,schedule: Schedule) 为每个字段定
我正在尝试将Writer和State(通过镜头)结合起来.我很确定我需要monad变换器,但我很难弄清楚如何使用T版本以及如何正确构建它.
现在我有一些模型(简化): case class Schedule(due: LocalDate) case class Task(title: String,schedule: Schedule) 为每个字段定义的镜头,titleL,scheduleL和dueL. 我的Writer类型的类型别名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 } 但是现在我不确定如何在最后一个功能中使用镜头或状态方法. 我希望能够做一些看起来像这样的事情: 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 } 我该怎么做呢?我是否正在与monad变形金刚合作?我可能已经错过的任何其他事情已经处理了我的情况? 编辑: 我有这样的工作,这个用例很好,但我想要更好地与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 } 解决方法
也许你可以进一步简化它,但这是我能得到的最好的.
据我所知,你不能直接在monad变压器中使用镜头,但你可以将镜头转换为状态,这与你需要的接近. 首先让我们定义我们的monad. def RWA[R,A] = ReaderWriterState.rwstMonad[Id.Id,R,Vector[String],A] val RST = RWA[String,Task] val RLS = RWA[Long,Schedule] def changeTitleV1 = for { title ← RST.ask // Reader part of transformer getting new title from the environment _ ← RST.modify(titleL =>= (_ ? title)) // `=>=` is converting lens to `A => A` _ ← RST.tell(Vector(s"I put the value $title"))) } yield () changeTitleV1.run("new title",Task("old title",Schedule(123))) //(Vector(I put the value new title),(),Task(new title,Schedule(123))) 我们将新标题作为此run函数的第一个参数传递,以便能够在monad中询问它. 在您的示例中 – 您希望在日志中写入某个条件,因此您需要获取初始状态以了解标题是否已更改.它变得不那么简洁了: def changeTitleV2 = for { title ← RST.ask task0 ← RST.get _ ← RST.put(titleL.set(task0,title)) _ ← RST.whenM(task0.title != title)(RST.tell(Vector(s"I put the value $title"))) } yield () 当然你可以为changeDue定义相同的东西: def changeDue = for { d0 ← RLS.get due ← RLS.ask _ ← RLS.put(dueL.set(t0,due)) _ ← RLS.whenM(d0.due != due)(RLS.tell(Vector(s"due changed to $due"))) } yield () 也就是说,我不太确定,你提出的解决方案要好得多. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |