scala - 避免丢失返回值中的类型信息

标签 scala implicit shapeless hlist

我正在尝试找到一种方法来避免丢失方法返回值中的类型信息。

我有以下内容:

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 时指定 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 的推断类型?

*无需指定 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$1@1f6a8bb8

附注

如果您不介意使用 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>

关于scala - 避免丢失返回值中的类型信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39486886/

相关文章:

java - ReactiveX:计算 Observable 中不同元素的频率

scala - 为递归数据结构定义 `Codec`

scala - Shapeless:Foo[T, U] 的 UnaryTCConstraint

math - ‘1 * BigInt(1)’ 如何工作,我该如何做?

android - Android 中的自定义隐式 Intent 不起作用

scala - 使用隐式字段实例化类

scala - 与不同类型但相同标签的无形状对齐

scala - 经销商(服务器)到经销商( worker )不工作

scala - 在 Scala 中,为什么不对类型参数发出未经检查的警告?

scala - "unresolved dependency"用于 SBT 上的 Spark 2.0.1