今天我碰到下面的问题就来了: 我有一些模式匹配回事,简化看起来像这样:斯卡拉模式与异步匹配(或任何单子)守卫
object Sync {
sealed trait MatchType
case object BigType extends MatchType
case object SmallType extends MatchType
case object EvenType extends MatchType
case object UnknownType extends MatchType
def syncPatternMatch(i: Int): MatchType = i match {
case _ if i > 100 => BigType
case _ if i < 3 => SmallType
case _ if i % 2 == 0 => EvenType
case _ => UnknownType
}
}
现在,不幸的是我想通了,我的警卫/提取者将是Future[Boolean]
。想象一下,他们调用外部Web服务来获得结果。 显然,我不能使用未来(或任何monad)的守卫或提取模式。
因此,现在我想检查每个条件异步,但打破了第一个成功的。
基本上我想要正常的monadic流的相反 - 意味着停下来第一次成功。
我的实现似乎很好,但我很好奇,看看在这种情况下是否有更简单的方法或者什么样的模式。
请记住,我的例子非常简单,为了成为一个例子。
import cats.data.EitherT
import cats.implicits._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
object Async {
sealed trait MatchType
case object BigType extends MatchType
case object SmallType extends MatchType
case object EvenType extends MatchType
case object UnknownType extends MatchType
type Match[B] = EitherT[Future, MatchType, B]
def isBigEnough(i: Int): Match[Unit] = Future(if(i > 100) Left(BigType) else Right(()))
def isVerySmall(i: Int): Match[Unit] = Future(if(i < 3) Left(SmallType) else Right(()))
def isEven(i: Int): Match[Unit] = Future(if(i % 2 == 0) Left(EvenType) else Right(()))
def otherwise: Match[MatchType] = Future.successful(Right(UnknownType))
implicit def liftFutureEither[A, B](f: Future[Either[A, B]]): EitherT[Future, A, B] = EitherT(f)
implicit def extractFutureEither[A, B](e: EitherT[Future, A, B]): Future[Either[A, B]] = e.value
def asyncPatternMatch(i: Int): Match[MatchType] = for {
_ <- isBigEnough(i)
_ <- isVerySmall(i)
_ <- isEven(i)
default <- otherwise
} yield default
asyncPatternMatch(10).foreach(either => println(either.fold(identity, identity)))
// EvenType
}
(顺便说一句,这是斯卡拉2.12)
我会很高兴的建议:)
我想你已经考虑得太过分了。试试'def asyncPatternMatch(i:Future [Int]):Match [MatchType] = i.map(syncPatternMatch)'。 –
我的卫兵是异步的,想象一下'isBigEnough'正在调用外部API来获得结果。 不要真的看到'Future [Int]'作为输入如何帮助我。 – rincewind