我正在学习 Scala 中的 Free monad,并且我整理了一个简单的代数示例,我可以使用猫将其提升为 Free monad。
这是我的代数
sealed trait ConsultationOp[A]
object consultation {
case class Create(c: Consultation) extends ConsultationOp[Unit]
case class Get(s: ConsultationId) extends ConsultationOp[Option[Consultation]]
}
我可以像这样使用它
def app = for {
c <- consultation.Create(Consultation("123", "A consultation"))
_ <- consultation.Get(c._id)
} yield ()
def interpreters = ConsultationInterpreter or UserInterpreter
app.foldMap(interpreters)
从ConsultationOp
to的提升Free
是隐式执行的。
(缺少很多细节,完整的工作实现在这里:https ://github.com/gabro/free-api )
到目前为止一切顺利,但是如果我需要提取consultation.Get
.
首先想到的是一个单子变换器,即类似
def app = for {
c <- consultation.Create(Consultation("123", "A consultation")).liftM[OptionT]
d <- OptionT(consultation.Get(c._id))
_ <- doSomethingAConsultation(d)
} yield ()
但它看起来很丑,而且感觉不对。
使用 Free monad 时堆叠 monadic 效果的美化方式(如果有的话)是什么?