猫EitherT.collectRight无法找到替代[未来]

时间:2017-12-02 01:55:40

标签: scala functional-programming scala-cats

我试图找到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常见问题不适用。

3 个答案:

答案 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是非常可疑的。看起来您真正需要的是getOrElsegetOrElseF。例如,这似乎与您的评论中描述的行为相匹配

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
}

还是我错过了什么?