避免丢失 return 值中的类型信息
Avoid losing type info in return value
我正在尝试找到一种方法来避免在我的方法的 return 值中丢失类型信息。
我有以下内容:
val defs0 = Default.mkDefault[Person, Some[String] :: Some[Int] :: HNil](Some("odd") :: Some(42) :: HNil)
使用 IntelliJs "Add type annotation" 给出类型:
Default.Aux[Person, ::[Some[String], ::[Some[Int], HNil]]]
这很好,除了我不想在调用 mkDefault 时指定 Person 的字段。所以我创建了这个:
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 的推断类型?
*无需指定 class Person
的字段
使用 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]]} = shapeless.Default$$anon@1f6a8bb8
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>
我正在尝试找到一种方法来避免在我的方法的 return 值中丢失类型信息。
我有以下内容:
val defs0 = Default.mkDefault[Person, Some[String] :: Some[Int] :: HNil](Some("odd") :: Some(42) :: HNil)
使用 IntelliJs "Add type annotation" 给出类型:
Default.Aux[Person, ::[Some[String], ::[Some[Int], HNil]]]
这很好,除了我不想在调用 mkDefault 时指定 Person 的字段。所以我创建了这个:
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 的推断类型?
*无需指定 class Person
的字段使用 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]]} = shapeless.Default$$anon@1f6a8bb8
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>