首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在Scala中的自由Monad中堆叠一元效果

在Scala中的自由Monad中堆叠一元效果
EN

Stack Overflow用户
提问于 2015-09-24 23:46:48
回答 1查看 977关注 0票数 20

我正在学习Scala中的Free monad,并且我已经组合了一个简单的代数示例,我可以使用cat将其提升为Free monad。

这是我的代数

代码语言:javascript
复制
sealed trait ConsultationOp[A]
object consultation {
  case class Create(c: Consultation) extends ConsultationOp[Unit]
  case class Get(s: ConsultationId) extends ConsultationOp[Option[Consultation]]
}

我可以像这样使用它

代码语言:javascript
复制
def app = for {
  c <- consultation.Create(Consultation("123", "A consultation"))
  _ <- consultation.Get(c._id)
} yield ()

def interpreters = ConsultationInterpreter or UserInterpreter
app.foldMap(interpreters)

其中,从ConsultationOpFree的提升是隐式执行的。

(缺少很多细节,完整的工作实现在这里:https://github.com/gabro/free-api)

到目前为止一切正常,但是如果我需要提取consultation.Get返回的可选值怎么办?

首先想到的是monad transformer,即类似于

代码语言:javascript
复制
def app = for {
  c <- consultation.Create(Consultation("123", "A consultation")).liftM[OptionT]
  d <- OptionT(consultation.Get(c._id))
  _ <- doSomethingAConsultation(d)
} yield ()

但它看起来很丑陋,而且感觉不对劲。

使用Free monad时,堆叠单体效果的美化方式是什么-如果有的话?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-02-09 16:24:03

在这些情况下,我看到的常见方法是使用traverse,这样你就可以像这样修改你的代码:

代码语言:javascript
复制
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并稍微修改代码,我没有尝试过,但其概念是:使用遍历。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32765658

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档