我正在尝试使用scalaz的ioeffect IO [E,A] monad编写一段非常有效的代码。
我正在尝试使用IO [E,A]进行高层重写的代码,其中包含有关存储在云中的文件的一些元数据。该代码尝试:
步骤的细节并不重要,但是我想做的事情是按照以下方式做一些事情:
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]
是围绕另一种类型的包装失败对象子方法中可能会发生故障?
答案 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
虽然很尴尬,但它的优点是能够存储所有出错的内容以及发生错误的上下文。