2016-09-14 57 views
2

我試圖找到一種方法來避免在我的方法的返回值中丟失類型信息。避免在返回值中丟失類型信息

我有以下幾點:

val defs0 = Default.mkDefault[Person, Some[String] :: Some[Int] :: HNil](Some("odd") :: Some(42) :: HNil) 

使用IntelliJs「添加類型的註釋」給出了類型:

Default.Aux[Person, ::[Some[String], ::[Some[Int], HNil]]] 

這是好的,但我不想給指定的人的領域,當我調用mkDefault。所以我創造了這個:

object MkDefault { 
    object toSome extends Poly1 { 
    implicit def default[P] = at[P](Some(_)) 
    } 

    def apply[P, L <: HList, D <: HList] 
    (p: P) 
    (implicit 
    lg: LabelledGeneric.Aux[P, L], 
    mpr: Mapper.Aux[toSome.type, L, D] 
): Default.Aux[P, D] = 
    Default.mkDefault[P, D](mpr(lg.to(p))) 
} 

現在我可以這樣做:

val defs1 = MkDefault(Person("odd", 42)) 

這是很好的,除了從IntellJ推斷出的類型如下:

Default.Aux[Person, HNil] 

我怎樣才能讓defs1的推斷類型等於推斷的defs0類型?

* 而不必指定類Person領域

+0

使用'mpr.Out'作爲輸出類型,而不是'D' – dk14

回答

2

使用mpr.Out代替D作爲輸出類型:

object MkDefault { 
    object toSome extends Poly1 { 
    implicit def default[P] = at[P](Some(_)) 
    } 

    def apply[P, L <: HList, D <: HList] 
    (p: P) 
    (implicit 
    lg: LabelledGeneric.Aux[P, L], 
    mpr: Mapper.Aux[toSome.type, L, D] 
): Default.Aux[P, mpr.Out] = 
    Default.mkDefault[P, D](mpr(lg.to(p))) 
} 

實施例:

scala> val defs1 = MkDefault(Person("odd", 42)) 
defs1: shapeless.Default[Person]{type Out = shapeless.::[Some[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("name")],String]],shapeless.::[Some[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("age")],Int]],shapeless.HNil]]} = [email protected] 

P.S.

如果你不介意Option而不是Some,您還可以使用AsOptions

val opt = Default.AsOptions[Person] 
val def3 = Default.mkDefault[Person, opt.Out](Some("aaa") :: Some(5) :: HNil) 

檢查:

scala> implicitly[def3.Out =:= ::[Option[String], ::[Option[Int], HNil]]] 
res12: =:=[def3.Out,shapeless.::[Option[String],shapeless.::[Option[Int],shapeless.HNil]]] = <function1> 
+0

太棒了,謝謝! 但是,爲了獲得_exact_相同的類型,我需要使用Generic而不是LabelledGeneric。如果沒有你的答案,就不會發現這一點,所以標記爲接受:) – eirirlar