合成scalaz io效果对象

时间:2018-12-03 23:20:24

标签: scala scalaz io-monad

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

我正在尝试使用IO [E,A]进行高层重写的代码,其中包含有关存储在云中的文件的一些元数据。该代码尝试:

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

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

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]的实例似乎没有组成。也就是说,由于例如downloadFile的IO签名针对其错误情况返回了DownloadFileFailure,而extractText返回了ExtractionFailure,因此这些单子似乎无法在{{ 1}}理解。

对我的顶级for理解而言,有没有一种简便的方法可以使它生成for,其中IO[ProcessFileFailure, IndexResponse]是围绕另一种类型的包装失败对象子方法中可能会发生故障?

1 个答案:

答案 0 :(得分:2)

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

例如:

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

虽然很尴尬,但它的优点是能够存储所有出错的内容以及发生错误的上下文。