Working with scala-cat's Ior data type I encountered the following problem:
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
In my last step I need to convert this type:
Ior[Failures, Ior[Failures, Seq[(Locale, File)]]]
into:
Ior[Failures, Seq[(Locale, File)]]
by somehow flatten
ing the Ior
(I want to accumulate all left Ior
's into the top-level Ior
). How can this be achieved?
You can literally just replace the ???
in result = ???
with analyzed.flatten
in your code and it will work perfectly, thanks to the flatten
syntax method provided by FlatMap
and the fact that Ior
has a FlatMap
instance when the left side is a semigroup (as it is here).
You can do a little better than that by replacing these two lines:
analyzed = fileIor.bimap(identity, analyzeTranslationFiles)
result = analyzed.flatten
With the following:
result = fileIor.flatMap(analyzeTranslationFiles)
…since any time you're using bimap
with identity
on the left side, you can replace it with map
, and any time you're using map
and then flatten
, you can replace both with flatMap
.