如何使用 Cats 在 Scala 中将 Option[A] 转换为 Either[String, B]?

How to transform Option[A] to Either[String, B] in Scala with Cats?

我创建了一些小代码示例,用于展示 cats 库的工作原理。当我在处理最后一个示例时,我注意到它可能更优雅:

import cats.effect.IO
import scala.collection.mutable.HashMap

val storage = HashMap[Int, String]().empty

override def deleteWord(id: Int): IO[Either[String, Unit]] =
  for {
    removedWord <- IO(storage.remove(id))
    result <- IO {
                removedWord.flatMap(_ => Some(())).toRight(s"Word with $id not found")
              }
  } yield result

有什么方法可以使用 cat 语法以更简洁的形式重写代码片段?

您不需要创建另一个 IO,因为 yield result 中的表达式已经被 IO 通过 for comprehension 包装。

def deleteWord(id: Int): IO[Either[String, Unit]] =
  for {
    removedWord <- IO(storage.remove(id))
    result = removedWord.map(_=>()).toRight(s"Word with $id not found")
  } yield result

甚至

def deleteWord(id: Int): IO[Either[String, Unit]] =
  for (removedWord <- IO(storage.remove(id)))
    yield removedWord.map(_=>()).toRight(s"Word with $id not found")

也许你过于简化了你的样本,但猫不会改进这种转换

import scala.collection.mutable.HashMap
import cats.implicits._

val storage = HashMap(1 -> "abc")

def deleteWord(id: Int) =
  storage
    .remove(id)
    .fold(s"Word with $id not found".asLeft[Unit])(_ => ().asRight)

deleteWord(1)
// Either[String, Unit] = Right(())
deleteWord(2)
// Either[String, Unit] = Left("Word with 2 not found")

我在 gitter cats chat 中收到的解决方案之一:

import cats.implicits._

override def deleteWord(id: Int): IO[Either[String, Unit]] =
  for {
    removedWord <- IO(storage.remove(id))
    result <- IO(removedWord.toRight(s"Word with $id not found").void)
  } yield result

这似乎正是我需要的