组成 scalaz io 效果对象
Composing scalaz io effect objects
我正在尝试将 scalaz 的 ioeffect IO[E,A] monad 用于一段非常有效的代码。
我试图用 IO[E,A] 在高层次上重写的代码需要一些关于存储在云中的文件的元数据。代码尝试:
- 下载文件
- 从文件中提取字符串
- 构建一个包含文件文本内容的 pojo
- 将 pojo 提交给某些 queue/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 签名 returns DownloadFileFailure
和 extractText
returns ExtractionFailure
,那些单子不能似乎无法理解 for
。
有没有一种简单的方法可以让我的顶级 for
理解组合成 IO[ProcessFileFailure, IndexResponse]
,其中 ProcessFileFailure
是围绕不同对象的某种包装失败对象子方法中可能发生的故障类型?
不幸的是,您确实需要一种方法将这些错误统一为一个常见错误:
例如:
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
它很笨拙,但它确实具有能够存储出错的所有内容以及出错发生的确切上下文的优势。
我正在尝试将 scalaz 的 ioeffect IO[E,A] monad 用于一段非常有效的代码。
我试图用 IO[E,A] 在高层次上重写的代码需要一些关于存储在云中的文件的元数据。代码尝试:
- 下载文件
- 从文件中提取字符串
- 构建一个包含文件文本内容的 pojo
- 将 pojo 提交给某些 queue/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 签名 returns DownloadFileFailure
和 extractText
returns ExtractionFailure
,那些单子不能似乎无法理解 for
。
有没有一种简单的方法可以让我的顶级 for
理解组合成 IO[ProcessFileFailure, IndexResponse]
,其中 ProcessFileFailure
是围绕不同对象的某种包装失败对象子方法中可能发生的故障类型?
不幸的是,您确实需要一种方法将这些错误统一为一个常见错误:
例如:
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
它很笨拙,但它确实具有能够存储出错的所有内容以及出错发生的确切上下文的优势。