Aujourd'hui, je suis tombé sur le problème suivant: J'ai eu quelques pattern matching en cours, simplifié qui ressemble à ceci:modèle Scala correspondant à async (ou tout monade) gardes
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
}
}
Maintenant, je me suis dit, malheureusement, sur , que mes gardes/extracteurs seront Future[Boolean]
. Imaginez qu'ils appellent un service Web externe pour obtenir le résultat. Évidemment, je ne peux pas utiliser le modèle de garde ou d'extraction avec un avenir (ou n'importe quelle monade). Donc, maintenant je veux vérifier chaque condition de manière asynchrone, mais casser la première réussie. Fondamentalement, je veux le contraire du flux monadique normal - ce qui signifie l'arrêt sur le premier succès.
Ma mise en œuvre semble bien fonctionner, mais je suis curieux de voir s'il y a un moyen plus simple ou quel type de modèle que vous utiliseriez dans ce cas. Rappelez-vous que mon exemple est extrêmement simple pour être un exemple.
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
}
(BTW. Il est scala 2.12)
Je serais heureux suggestions :)
Je pense que vous avez factorisé trop loin. Essayez 'def asyncPatternMatch (i: Futur [Int]): Match [MatchType] = i.map (syncPatternMatch)'. –
Mh mes gardes sont asynchrones, imaginez 'isBigEnough' appelle une API externe pour obtenir le résultat. Je ne vois pas vraiment comment une entrée 'Future [Int]' en tant qu'entrée m'aiderait ici. – rincewind