2016-06-24 16 views
5

मुझे Future[Either[A, B]] मिला है और B से Future[C] प्रदान करने वाला एक फ़ंक्शन है।भविष्य [या तो [ए, बी]] भविष्य में [या तो [ए, सी]] एक (बी => भविष्य [सी]) का उपयोग कर

मुझे Future[Either[A, B]] से Future[Either[A, C]] को बदलने की आवश्यकता है।

क्या Future[Either[A, C]] प्राप्त करने का कोई सीधा तरीका नहीं है और Future[Either[A, Future[C]]] नहीं है?

मैं की तरह कुछ के बारे में सोच रहा हूँ:

val eventuallyInitialValue: Future[Either[A, B]] = ??? 
val result: Future[Either[A, C]] = for { 
    e: Either[A, B] <- initialValue 
    c: C <- service.getValue(e.right) 
} yield e.right.map(_ => c) 

यह service.getValue(e.right) के बाद से सिर्फ छद्म कोड संकलन नहीं करता है। ऐसा करने का सही तरीका क्या होगा?

उत्तर

7

यह है कि मैं क्या लेकर आए हैं एक Right इसके लिए।

3

आप B => Future[C] फ़ंक्शन को Either[E, B] => Future[Either[E, C]] फ़ंक्शन में उठाकर ऐसा कर सकते हैं और फिर आप मूल भविष्य पर flatMap कर सकते हैं।

type B = Int 
type A = String 
type C = Long 
val eitherF: Future[Either[A, B]] = ??? 
def f(b: B): Future[C] = ??? 

val mapped: Future[Either[A, C]] = eitherF.flatMap { 
    case Left(a) => 
    Future.successful(Left(a)) 
    case Right(b) => 
    f(b).map(Right(_)) 
} 

मूल रूप से आप भविष्य flatMap सकते हैं और फिर अगर यह एक बाएं सिर्फ सफलता लौटने के लिए, अगर यह एक सही है आप भविष्य और नक्शा आवेदन कर सकते हैं:

eventuallyInitialValue.flatMap { 
    case Left(e) => Future.successful(Left(e)) 
    case Right(r) => bToFC(r).map(Right.apply _) 
} 
+0

धन्यवाद। इसे सिर्फ दाएं के रूप में वापस करने की आवश्यकता है: बीटीओएफसी (आर)। मैप (दाएं (_)) –

+0

@ अलबान: हाँ, संपादित किया गया है कि – Daenyth

+0

यदि आप 'भविष्य.प्ली' के बजाय 'Future.successful' का उपयोग करते हैं तो आप इससे बचेंगे थ्रेड पूल पर 'बाएं (ई) 'बनाना। –

6

यहां स्केलज़ समाधान है। ध्यान दें कि यह या तो स्कालाज़ संस्करण का उपयोग करता है।

class A 
class B 
class C 

val initial: Future[A \/ B] = (new B).right.point[Future] 
val f: B => Future[C] = _ => (new C).point[Future] 

val result: Future[A \/ C] = (for { 
           e <- EitherT(initial) 
           res <- EitherT(f(e).map(_.right)) 
           } yield res).run 

यह मूल रूप से एक ही क्या @Ende Neu किया, लेकिन मिलान और rewrapping इकाई ट्रांसफार्मर में छिपा हुआ है है।

+0

यह प्रारंभिक नहीं होगा। प्रारंभिक.फ्लैटमैप (_। गुना (पहचान, (दाएं। एपली _) लिखें comp) '? – Daenyth

+0

यह मेरे लिए संकलित नहीं है, और मुझे यकीन नहीं है कि यह काम कर सकता है लेकिन यदि यह दिलचस्प लग रहा है और शायद आपको इसे उत्तर के रूप में पोस्ट करना चाहिए। –

+0

आप सही हैं, प्रकार गलत है; आपको 'f' के परिणाम पर 'दाएं' को मानचित्र करने की आवश्यकता है – Daenyth

1

बिल्लियों वर्तमान में OptionT और XorT जो एक समारोह B => F[C] लेता है के लिए एक विधि semiflatMap जोड़ने के लिए an open pull request है।

हम scalaz.EitherT के लिए एक समान कार्य बना सकते हैं:

import scalaz._, Scalaz._ 

def semiFlatMap[F[_]: Monad, A, B, C](e: EitherT[F, A, B])(f: B => F[C]): EitherT[F, A, C] = 
    e.flatMap(f andThen EitherT.right[F, A, C]) 

तो फिर तुम कर सकता है:

import scala.concurrent.Future 
import scala.concurrent.ExecutionContext.Implicits.global 

val futureEither: Future[Either[String, Int]] = Future.successful(Right(1)) 
val f: Int => Future[Long] = i => Future.successful(i + 1L) 

val appliedF: EitherT[Future,String,Long] = 
    semiFlatMap(EitherT.fromEither(futureEither))(f) 

val futureEither2: Future[Either[String, Long]] = appliedF.run.map(_.toEither) 
संबंधित मुद्दे