使用Scalaz IO效应对象组合

3
我正在尝试使用Scalaz的IO效应单子IO[E,A],处理一段非常具有效果的代码。我希望用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]的实例似乎无法组合。例如,downloadFile方法的IO签名返回DownloadFileFailure作为其错误场景,而extractText返回ExtractionFailure,这些单子似乎无法在for循环中组合。
是否有一种简单的方法使我的顶级for循环组合起来,以便它会产生一个IO[ProcessFileFailure, IndexResponse],其中ProcessFileFailure是一种围绕子方法中可能发生的不同类型故障的包装故障对象?
1个回答

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循环将变成:

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

虽然有些尴尬,但这种方法确实有一个优点,就是能够存储所有出了问题的内容以及发生问题的具体上下文。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接