У меня есть следующая функция:
def function(i: Int): IO[Either[String, Option[Int]]] = ???
Мне нужна функция вида:
def foo(either: Either[String, Option[Int]]): IO[Either[String, Option[Int]]]
и я хочу, чтобы он имел следующее поведение:
def foo1(either: Either[String, Option[Int]])
: IO[Either[String, Option[Int]]] = either match {
case Right(Some(i)) => bar(i)
case Right(None) => IO.pure(None.asRight)
case Left(s) => IO.pure(s.asLeft)
}
Я хочу сделать это менее явно, поэтому я попробовала BothT:
def foo2(either: Either[String, Option[Int]]):
IO[Either[String, Option[Int]]] = {
val eitherT = for {
maybe <- EitherT.fromEither[IO](either)
int <- EitherT.fromOption(maybe, "???")
x <- EitherT(bar(int))
} yield x
eitherT.value
}
но это означает, что Right(None)
будет сопоставлено с IO(Left("???"))
, чего я не хочу.
существует ли альтернативная формулировка с
EitherT
без выражения соответствия, эквивалентная реализацииfoo1
?что более важно, как будет выглядеть реализация, использующая
map/traverse/biTraverse/etc.
(и не совпадающая ни с одной из опций)?
p.s. Намерение здесь состоит в том, чтобы определить функцию «карты» для следующего типа:
trait Lookup[F[_], K, A] {
def get(key: K): F[Either[FormatError, Option[A]]]
}