scala - IO 和 Future[Option] monad 转换器

标签 scala scalaz monad-transformers io-monad

我试图弄清楚如何使用 scalaz7 IO 和 monad 转换器以优雅的纯函数风格编写这段代码,但我无法理解它。

想象一下我有这个简单的 API:

def findUuid(request: Request): Option[String] = ???
def findProfile(uuid: String): Future[Option[Profile]] = redisClient.get[Profile](uuid)

使用这个 API,我可以轻松地使用 OptionT 转换器编写不纯的函数,如下所示:
val profileT = for {
  uuid <- OptionT(Future.successful(findUuid(request)))
  profile <- OptionT(findProfile(uuid))
} yield profile
val profile: Future[Option[Profile]] = profileT.run

正如您所注意到的 - 此函数包含具有副作用的 findProfile()。我想在 IO monad 内部隔离这种效果并在纯函数之外解释,但不知道如何将它们组合在一起。
def findProfileIO(uuid: String): IO[Future[Option[Profile]]] = IO(findProfile(uuid))

val profileT = for {
  uuid <- OptionT(Future.successful(findUuid(request)))
  profile <- OptionT(findProfileIO(uuid)) //??? how to put Option inside of the IO[Future[Option]]
} yield profile
val profile = profileT.run //how to run transformer and interpret IO with the unsafePerformIO()??? 

关于如何完成的任何建议?

最佳答案

IO更适用于同步效果。 Task是你想要的更多!
看这个问答:What's the difference between Task and IO in Scalaz?

您可以转换您的 FutureTask然后有一个这样的 API:

def findUuid(request: Request): Option[String] = ??? 
def findProfile(uuid: String): Task[Option[Profile]] = ???

这是有效的,因为 Task可以表示同步和异步操作,所以 findUuid也可以包裹在Task而不是 IO .

然后你可以将这些包裹在 OptionT 中:
val profileT = for {
  uuid <- OptionT(Task.now(findUuid(request)))
  profile <- OptionT(findProfileIO(uuid))
} yield profile

然后在最后的某个地方你可以运行它:
profileT.run.attemptRun

查看此链接以将 future 转换为任务,反之亦然:Scalaz Task <-> Future

关于scala - IO 和 Future[Option] monad 转换器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44887942/

相关文章:

scala - BodyParser 根据请求体返回结果

scala - 如何使用 Akka 远程处理通过 CLI 向远程参与者发送消息?

list - 什么是 DList?

scala - 在 Scalatest 和 Argonaut.io 中导致编译失败的模糊隐式转换

scala - `effect` 中的 `scalaz-effect` 是什么意思

scala - 在 Scalaz 中自定义 Future、Either 和 Writer 的组合

scala - 有什么方法可以指定 scalikejdbc 的自定义连接参数吗?

scala - java.lang.ClassNotFoundException : org. apache.spark.sql.Dataset

haskell - Monad 是否有标准名称(和库实现)将计算隐藏在构造函数后面?