2016-11-06 9 views
5

मैं अगली कक्षा है छोड़ें:निराकार परिवर्तित मामले वर्ग और सभी विकल्प क्षेत्रों

case class Foo(a: Option[Int], b: Option[String], c: Option[Double]) 

के रूप में आप देख सकते हैं, सभी क्षेत्रों वैकल्पिक है, मैं HList या टपल में इस वर्ग को परिवर्तित करना चाहते हैं,

की तरह
val f1 = Foo(Some(1) , None, Some(3D)) 
val f2 = Foo(None, "foo") 

val result1 = f1.to[Int::Double::HNil] // => 1::3D 
val result2 = f2.to[String::HNil] // "foo" 

क्या यह प्रतिबिंब के बिना संभव है?

+1

आप क्या करना चाहते हैं उदा। 'f1.to [स्ट्रिंग :: एचएनआईएल] 'मामला? ऐसा करना निश्चित रूप से संभव है, लेकिन आपको यह तय करने की आवश्यकता होगी कि मामले को कैसे संभालना है जहां लापता-नस्ल केवल रनटाइम पर जाना जाता है। –

+0

मुझे लगता है - अपवाद, लेकिन संभव वापसी विकल्प [टी <: एचएलआईस्ट] आकारहीन 'कास्ट' की तरह, और मामले में 'f1.to [स्ट्रिंग :: एचएनआईएल]' वापसी कोई नहीं – mike

उत्तर

6

शेपलेस में मौजूदा प्रकार के वर्गों (NatTRel और) के साथ ऐसा करना संभव हो सकता है, लेकिन मुझे 100% यकीन नहीं है, और यह एक ऐसा मामला है जहां मैं अपना खुद का प्रकार लिखूंगा वर्ग:

import shapeless._ 

trait OptionalPieces[L <: HList, S <: HList] { 
    def apply(l: L): Option[S] 
} 

object OptionalPieces extends LowPriorityOptionalPieces { 
    implicit val hnilOptionalPieces: OptionalPieces[HNil, HNil] = 
    new OptionalPieces[HNil, HNil] { 
     def apply(l: HNil): Option[HNil] = Some(HNil) 
    } 

    implicit def hconsOptionalPiecesMatch[H, T <: HList, S <: HList](implicit 
    opt: OptionalPieces[T, S] 
): OptionalPieces[Option[H] :: T, H :: S] = 
    new OptionalPieces[Option[H] :: T, H :: S] { 
     def apply(l: Option[H] :: T): Option[H :: S] = for { 
     h <- l.head 
     t <- opt(l.tail) 
     } yield h :: t 
    } 
} 

sealed class LowPriorityOptionalPieces { 
    implicit def hconsOptionalPiecesNoMatch[H, T <: HList, S <: HList](implicit 
    opt: OptionalPieces[T, S] 
): OptionalPieces[Option[H] :: T, S] = 
    new OptionalPieces[Option[H] :: T, S] { 
     def apply(l: Option[H] :: T): Option[S] = opt(l.tail) 
    } 
} 

यह गवाह है कि Lकम से कमS के तत्वों के क्रम में, Option में लिपटे के सभी शामिल हैं, और आप उन्हें क्रम (सुरक्षित रूप से) में खोलने में एक रास्ता देती है। क्या तुम सच में अपवाद थे तो

scala> val f1 = Foo(Some(1) , None, Some(3D)) 
f1: Foo = Foo(Some(1),None,Some(3.0)) 

scala> val f2 = Foo(None, Some("foo"), None) 
f2: Foo = Foo(None,Some(foo),None) 

scala> val result1 = f1.to[Int :: Double :: HNil] 
result1: Option[shapeless.::[Int,shapeless.::[Double,shapeless.HNil]]] = Some(1 :: 3.0 :: HNil) 

scala> val result2 = f2.to[String :: HNil] 
result2: Option[shapeless.::[String,shapeless.HNil]] = Some(foo :: HNil) 

, तो आप सिर्फ वाक्य रचना वर्ग में .get कह सकते हैं, लेकिन यह है कि:

हम तो इस तरह एक वाक्य रचना सहायक वर्ग को परिभाषित कर सकते हैं:

implicit class OptionalPiecesSyntax[A, R <: HList](a: A)(implicit 
    gen: Generic.Aux[A, R] 
) { 
    def to[S <: HList](implicit op: OptionalPieces[gen.Repr, S]): Option[S] = 
    op(gen.to(a)) 
} 

और फिर एक बुरा विचार की तरह लगता है।

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