我正在学习Scala中的Free monad,并且我已经组合了一个简单的代数示例,我可以使用cat将其提升为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
到Free
的提升是隐式执行的。
(缺少很多细节,完整的工作实现在这里:https://github.com/gabro/free-api)
到目前为止一切正常,但是如果我需要提取consultation.Get
返回的可选值怎么办?
首先想到的是monad transformer,即类似于
def app = for {
c <- consultation.Create(Consultation("123", "A consultation")).liftM[OptionT]
d <- OptionT(consultation.Get(c._id))
_ <- doSomethingAConsultation(d)
} yield ()
但它看起来很丑陋,而且感觉不对劲。
使用Free monad时,堆叠单体效果的美化方式是什么-如果有的话?
发布于 2017-02-09 16:24:03
在这些情况下,我看到的常见方法是使用traverse,这样你就可以像这样修改你的代码:
import cats.syntax.traverse._
import cats.instances.option._
// ...
def app = for {
c <- consultation.Create(Consultation("123", "A consultation"))
d <- consultation.Get(c._id)
_ <- d.traverseU(doSomethingAConsultation(_))
} yield ()
imho,它比monad transformer替代方案干净得多。请注意,您可能需要一些其他的import
并稍微修改代码,我没有尝试过,但其概念是:使用遍历。
https://stackoverflow.com/questions/32765658
复制相似问题