我试图找到Cats if(root.index == i)
的示例。我有一个EitherT.collectRight
,当我做EitherT[Future, String, Event]
时,我得到了
collectRight,
我在范围内隐含Error:(79, 18) could not find implicit value for parameter FA: cats.Alternative[scala.concurrent.Future]
elem.collectRight
,因此this常见问题不适用。
答案 0 :(得分:3)
Alternative[Future]
没有实例,也没有实例。这是类型定义:
trait Alternative[F[_]] extends Applicative[F] with MonoidK[F]
Applicative[Future]
没问题。但MonoidK[F]
对Future
没有意义。来自对MonoidK
的评论:
Monoid[A]
允许合并A
个值,也就是那里 是一个“空”A
值,用作身份。
MonoidK[F]
允许合并两个F[A]
值,适用于任何A
。它 也意味着对于任何A
,都会有一个“空”F[A]
值。该 组合操作和空值仅取决于F
的结构,而不是A
的结构。
您如何为任何Future[A]
构建“空”A
?你如何将两个Future[A]
组合成一个?您可以使用List
了解这是如何实现的,但对我而言Future
是无意义的。也许你有一些你期望的行为,你可以自己实现Applicative[Future]
。但我怀疑真正的问题是你想要collectRight
以外的东西。
例如,您对此有何看法?
val e: EitherT[Future, String, Event] = Future(Left("hello"))
val result: Future[Event] = e.collectRight // should return what?... failure?
答案 1 :(得分:1)
这是对Abhijit Sarkar对JoeK的答案的评论的回答,该答案对于评论来说太大了。
首先,我同意Joe的观点,即您尝试使用collectRight
是非常可疑的。看起来您真正需要的是getOrElse
或getOrElseF
。例如,这似乎与您的评论中描述的行为相匹配
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
case class Event(val a: Int)
val eGood: EitherT[Future, String, Event] = EitherT[Future, String, Event](Future(Right(Event(42))))
val resultGood: Future[Event] = eGood.getOrElseF(Future.failed(new NoSuchElementException("whatever")))
val eBad: EitherT[Future, String, Event] = EitherT[Future, String, Event](Future(Left("hello")))
val resultBad: Future[Event] = eBad.getOrElseF(Future.failed(new NoSuchElementException("whatever")))
println("good = " + scala.concurrent.Await.result(resultGood, 1 second))
println()
scala.concurrent.Await.result(resultBad, 1 second)) // don't need println as there will be exception anyway
打印
good =活动(42)
线程“main”中的异常java.util.NoSuchElementException:无论如何
在sg.cats.CatsMain $。$ anonfun $ resultBad $ 1(CatsMain.scala:32))
在......
请注意,Future.failed(new NoSuchElementException("whatever"))
实际上是Alternative[Future]
应该具有empty
实现的内容。这是没有适合所有场景的解决方案的地方之一。尽管如此,如果您总是无法输入并且您遇到与所有情况相同的失败,那么您可以创建隐式操作,例如:
final class MyEitherFutureOps[A, B](val eab: EitherT[Future, A, B]) extends AnyVal {
import cats.instances.future._
def rightOrFailure(implicit ec: ExecutionContext): Future[B] = eab.getOrElseF(Future.failed(new NoSuchElementException("whatever")))
}
object MyEitherFutureOps {
implicit def ops[A, B](eab: EitherT[Future, A, B]): MyEitherFutureOps[A, B] = new MyEitherFutureOps[A, B](eab)
}
然后您可以将其用作
import MyEitherFutureOps._
val eGood: EitherT[Future, String, Event] = EitherT[Future, String, Event](Future(Right(Event(42))))
val resultGood: Future[Event] = eGood.rightOrFailure
val eBad: EitherT[Future, String, Event] = EitherT[Future, String, Event](Future(Left("hello")))
val resultBad: Future[Event] = eBad.rightOrFailure
与上例中的效果相同。
答案 2 :(得分:1)
帖子现在已经快2年了,但是简单如何:
val e: EitherT[Future, String, Event] = ???
val result: Future[Event] = e.value.flatMap {
case Right(event) => Future.successful(event)
case Left(e) => Future.failed(new NoSuchElementException("whatever with: " + e))
//case Left(e) => Future.successful(???) //some recover from String to Event
}
还是我错过了什么?