2015-06-11 6 views
5

चलो कहते हैं कि हम इस करते हैं:HList डाली varargs को

def join[A, B](a: A, b: B) 
def join[A, B, C](a: A, b: B, c: C) // etc 

मूल रूप से 20 प्रकार के तर्क के लिए अतिभारित तरीकों का एक बहुत।

और फिर निम्न जो HList पर एक यूनरी प्रकार की बाधा लागू करके के-सूची बना रहा है, जैसे कि सभी आंतरिक तत्व Task[_] प्रकार के हैं।

class Test(L <: HList : *->*[Task]#λ](val deps : L = HNil) 

यह एक Task[A1, A2, A3] आदि के लिए deps कन्वर्ट करने के लिए जहां A1, A2, A3HList के भीतरी प्रकार के होते हैं संभव है?

तो के लिए:

Task[(Int, String, Boolean)] 

और तर्कों के किसी भी संख्या के लिए ऐसा करते हैं:

val hls = Task(1) :: Task("string") :: Task9(true) :: HNil 

एक पुन: प्राप्त करें? मैं पहले से ही किसी भी तर्क के लिए Task[A], Task[B] को Task[A, B] में परिवर्तित कर सकता हूं, बस HList से varargs या इसी तरह के लिए प्राप्त करने की आवश्यकता है।

+0

@TravisBrown यह वर्तमान में एक ट्विटर भविष्य 'Future.join' के साथ शामिल हो गया है। नया 'Futures.join' अधिभार संभवतः मेरे अभ्यास के उद्देश्य के लिए' एचएलआईटी 'अनुकूल संस्करण में फिर से लिखा जा सकता है, लेकिन मुझे एचएलिस्ट से टुपल तक varargs तक जाने और आकार प्राप्त करने के लिए आकारहीन ओप के बारे में पर्याप्त जानकारी नहीं है। – flavian

+0

आह, क्षमा करें-बहुत जल्दी पढ़ना। ओवरलोडेड 'जॉइन' विधियों का उपयोग करना संभवतः व्यावहारिक रूप से नहीं है, लेकिन 'शामिल' करने के लिए नेस्टेड जोड़ी कॉल का उपयोग करना संभव है- मैं इस शाम को एक उदाहरण डाल सकता हूं अगर कोई मुझे इसके साथ मारता है। –

उत्तर

5

स्कैला के परिप्रेक्ष्य से join विधियों में कुछ भी सामान्य नहीं है लेकिन उनका नाम है, इसलिए बहुत सारे बॉयलरप्लेट (या कस्टम मैक्रो) के बिना इन संदर्भों में उनका उपयोग करना वास्तव में संभव नहीं है। इसके बजाय ट्विटर पर Future पर बार-बार join का उपयोग करना संभव है। आप एक नए प्रकार के वर्ग बनाकर ऐसा कर सकते हैं:

import shapeless._ 

trait FutureSequence[L <: HList] extends DepFn1[L] 

इस प्रकार का वर्ग गवाह होगा कि एक hlist L वायदा की पूरी तरह से बना है, और यह हमें एक Future[T], जहां में उन वायदा क्रम के लिए एक रास्ता दे देंगे TL (*->*) में प्रत्येक वायदा के अंदर के प्रकारों से बना हुआ टुपल है, जो हमें इसका पहला हिस्सा देता है, लेकिन दूसरी सुविधा का समर्थन नहीं करता है, या दूसरे भाग को आसानी से करने का कोई भी तरीका नहीं है)।

साथी वस्तु सभी दिलचस्प काम करता है:

import com.twitter.util.Future 
import shapeless.ops.tuple.Prepend 

object FutureSequence { 
    type Aux[L <: HList, Out0] = FutureSequence[L] { type Out = Out0 } 

    implicit def hnilFutureSequence: Aux[HNil, Future[Unit]] = 
    new FutureSequence[HNil] { 
     type Out = Future[Unit] 
     def apply(l: HNil): Future[Unit] = Future.Unit 
    } 

    implicit def hconsFutureSequence[H, T <: HList, OutT](implicit 
    fst: Aux[T, Future[OutT]], 
    pre: Prepend[Tuple1[H], OutT] 
): Aux[Future[H] :: T, Future[pre.Out]] = new FutureSequence[Future[H] :: T] { 
    type Out = Future[pre.Out] 

    def apply(l: Future[H] :: T): Future[pre.Out] = 
     l.head.join(fst(l.tail)).map { 
     case (h, t) => pre(Tuple1(h), t) 
     } 
    } 
} 

हम प्रेरण का उपयोग कर रहे यहाँ-पहले हम HNil (हमारे आधार मामले) अनुक्रम के तरीके का वर्णन, और फिर हम क्रम के लिए कैसे Future[H] :: T यह देखते हुए कि वर्णन हम जानते हैं कि T अनुक्रम कैसे करें।

अगला हम उपयोग करने के लिए यह आसान बनाने के लिए एक विधि को परिभाषित करेंगे:

def sequence[L <: HList](l: L)(implicit fs: FutureSequence[L]): fs.Out = fs(l) 

और फिर अगर हम कुछ उदाहरण मिल गया है:

val good = Future(1) :: Future("string") :: Future(true) :: HNil 
val bad = Future(1/0) :: Future("string") :: Future(true) :: HNil 

हम उन्हें क्रम सकते हैं:

scala> import com.twitter.util.Await 
import com.twitter.util.Await 

scala> Await.result(sequence(good)) 
res0: (Int, String, Boolean) = (1,string,true) 

scala> sequence(bad).onFailure(println) 
java.lang.ArithmeticException:/by zero 
res1: com.twitter.util.Future[(Int, String, Boolean)] = ... 

आपको अपने कक्षा के कन्स्ट्रक्टर में FutureSequence उदाहरण की आवश्यकता हो सकती है, या यो पर विशिष्ट तरीकों पर यूआर कक्षा

+1

यह या तो आप या मील थे जो इसका उत्तर दे सकते थे, और मुझे पता है कि माइल्स तक पहुंचना मुश्किल है। परेशानी लेने के लिए बहुत धन्यवाद, यह वास्तव में वास्तव में अच्छा है – flavian

+0

मुझे पहुंचने में कठिनाई नहीं है ... यह @travisbrown है जो निशान से अविश्वसनीय रूप से त्वरित है! :-) –

संबंधित मुद्दे