Сегодня я наткнулся на следующую проблему: я имел некоторые типы соответствия шаблону происходит, упрощена глядя, как это:Scala шаблону с асинхронном (или любой монады) оберегает
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]
. Представьте, что они называют внешний веб-сервис, чтобы получить результат. Очевидно, я не могу использовать рисунок стража или экстрактора с Будущим (или любой монадой).
Итак, теперь я хочу проверить каждое условие асинхронно, но перерыв на первом успешном.
В принципе, я хочу, чтобы противоположность нормального монадического потока - означает остановку при первом успехе.
Моя реализация, похоже, работает хорошо, но я - любопытство, чтобы увидеть, есть ли более простой способ или какой шаблон вы будете использовать в этом случае.
Помните, что мой пример чрезвычайно прост для примера.
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 Scala)
Я был бы рад за предложения :)
Я думаю, что вы зашли слишком далеко. Попробуйте 'def asyncPatternMatch (i: Future [Int]): Match [MatchType] = i.map (syncPatternMatch)'. –
Mh Мои охранники асинхронны, представьте, что 'isBigEnough' вызывает внешний api для получения результата. На самом деле не вижу, как мне поможет вход 'Future [Int]'. – rincewind