首页 > 解决方案 > 组成 scalaz io 效果对象

问题描述

我正在尝试将 scalaz 的 ioeffect IO[E,A] monad 用于一段非常有效的代码。

我试图用 IO[E,A] 在高级别重写的代码需要一些关于存储在云中的文件的元数据。该代码试图:

  1. 下载文件
  2. 从文件中提取字符串
  3. 构建一个包含文件文本内容的 pojo
  4. 将 pojo 提交给一些队列/restful 服务

步骤的细节并不那么重要,但我想做的是按照以下方式做一些事情:

def processShareActivity(fileObject: FileObject): IO[ProcessFileFailure, IndexResponse] = {
    for {
        file <- downloadFile (fileObject)
        text <- extractText (file)
        searchFileObject <- IO.point(buildSearchFileObject (fileObject, file, text))
        indexedResponse <- indexSearchFileObject (searchFileObject)
    } yield indexedResponse
}

def indexSearchFileObject(fileObject: SearchFileObject): IO[IndexFailure, IndexResponse] = ???

def buildSearchFileObject(fileObject: FileObject, file: File, str: String): SearchFileObject = ???

def extractText(file: File): IO[ExtractionFailure, String] = ???

def downloadFile(fileObject: FileObject): IO[DownloadFileFailure, File] = ???

问题是,一个实例似乎IO[E,A]IO[F,B]没有组合。也就是说,由于 exampledownloadFile的 IO 签名DownloadFileFailure为其错误场景返回并extractText返回ExtractionFailure,因此这些 monad 似乎无法构成for理解。

是否有一种简单的方法可以让我的顶级for理解进行组合,从而导致在子方法中可能发生的不同类型的故障IO[ProcessFileFailure, IndexResponse]周围ProcessFileFailure存在某种包装故障对象?

标签: scalascalazio-monad

解决方案


不幸的是,您确实需要一种方法将这些错误统一为一个常见错误:

例如:

sealed trait ProcessFileFailure
object ProcessFileFailure {
   case class Index(e: IndexFailure) extends ProcessFileFailure
   case class Extraction(e: ExtractionFailure) extends ProcessFileFailure
   case class Download(e: DownloadFileFailure) extends ProcessFileFailure
}

你的理解将变成:

for {
        file <- downloadFile (fileObject).leftMap(ProcessFileFailure.Download)
        text <- extractText (file).leftMap(ProcessFileFailure.Extraction)
        searchFileObject <- IO.point(buildSearchFileObject (fileObject, file, text))
        indexedResponse <- indexSearchFileObject (searchFileObject).leftMap(ProcessFileFailure.Index)
    } yield indexedResponse

它很尴尬,但它确实具有能够存储所有错误以及发生错误的上下文的优势。


推荐阅读