首页 > 解决方案 > 用 scala-cats 展平嵌套的 Ior's

问题描述

使用 scala-cat 的Ior数据类型我遇到了以下问题:

import cats._
import cats.data._
import cats.implicits._

type Locale = String
type FailureMessage = String
type Failures = NonEmptyList[FailureMessage]

private def listTranslationFiles(): IO[FailureMessage Either Array[File]] = ???

private def analyzeTranslationFiles(fs: Array[File]): Failures Ior Seq[(Locale, File)] = ???

private def readTranslations(): IO[Failures Ior Seq[(Locale, File)]] = for {
    files <- listTranslationFiles()
    fileIor = if(files.isLeft) (NonEmptyList(files.left.get, Nil): Failures).leftIor
              else files.right.get.rightIor
    // fileIor: Ior[Failures, Array[File]]
    analyzed = fileIor.bimap(identity, analyzeTranslationFiles)
    // analyzed: Ior[Failures, Ior[Failures, Seq[(Locale, File)]]]
    result = ??? //  how do I 'flatten' analyzed here?
} yield result

在我的最后一步中,我需要转换这种类型:

Ior[Failures, Ior[Failures, Seq[(Locale, File)]]]

进入:

Ior[Failures, Seq[(Locale, File)]]

通过某种方式flattenIor我想将所有 left 累积Ior到顶层Ior)。如何做到这一点?

标签: scalafunctional-programmingscala-cats

解决方案


您可以从字面上将代码中的???inresult = ???替换为analyzed.flatten,它会完美地工作,这要归功于提供的flatten语法方法以及当左侧是半群时有一个实例FlatMap的事实(就像这里一样)。IorFlatMap

通过替换这两行,您可以做得更好:

analyzed = fileIor.bimap(identity, analyzeTranslationFiles)
result = analyzed.flatten

具有以下内容:

result = fileIor.flatMap(analyzeTranslationFiles)

…因为您在左侧使用bimapwith的任何时候,都可以将其替换为,并且在您使用and 然后的任何时候,您都可以将两者都替换为。identitymapmapflattenflatMap


推荐阅读