How to implicitly figure out the type at the head of a shapeless HList

空扰寡人 提交于 2021-02-05 12:04:49

问题


Lets say I have the following:

case class TestField(value: String)
case class TestField2(value: String)

implicit class ProductExtensions[T <: Product](val value T) extends AnyVal {

  def mapTo[R <: Product](implicit tGen: Generic.Aux[T, String :: HNil], rGen: Generic.Aux[R, String :: HNil]: R = ???

}

val testField2 = TestField("my value").mapTo[TestField2]
// TestField2("my value")

Can I "genersize" the mapTo function to work for types other than String without having to specify the type?

Note TestField nor TestField2 implement AnyVal (nor do I want them to), so I can't use Unwrapped.

Edit

@Dmytro_Mitin answer works in my example above, but if I extend the example to this:

implicit class ProductExtensions[T <: Product](val value T) extends AnyVal {

  def mapTo[R <: Product](implicit tGen: Generic.Aux[T, String :: HNil], rGen: Generic.Aux[R, String :: HNil], o: OtherImplicit[String]): R = ???

}

...so I am kind of looking for this to work (but it doesn't):

implicit class ProductExtensions[T <: Product, U](val value T) extends AnyVal {

  def mapTo[R <: Product](implicit tGen: Generic.Aux[T, U :: HNil], rGen: Generic.Aux[R, U :: HNil], o: OtherImplicit[U]): R = ???

}

Any ideas?


回答1:


Here is generalized version

implicit class ProductExtensions[T <: Product, L <: HList](val value: T) extends AnyVal {
  def mapTo[R <: Product](implicit tGen: Generic.Aux[T, L], rGen: Generic.Aux[R, L]): R = rGen.from(tGen.to(value))
}

The Type Astronaut’s Guide to Shapeless. 6.3 Case study: case class migrations https://books.underscore.io/shapeless-guide/shapeless-guide.html#sec:ops:migration


New version

import shapeless.ops.hlist.IsHCons

implicit class ProductExtensions[T <: Product, L <: HList, U, L1 <: HList](val value: T) extends AnyVal {
  def mapTo[R <: Product](implicit 
                          tGen: Generic.Aux[T, L], 
                          rGen: Generic.Aux[R, L], 
                          isHCons: IsHCons.Aux[L, U, L1], 
                          o: OtherImplicit[U]
                         ): R = rGen.from(tGen.to(value))
}

4.3 Chaining dependent functions https://books.underscore.io/shapeless-guide/shapeless-guide.html#sec:type-level-programming:chaining

Scala shapeless Generic.Aux implicit parameter not found in unapply



来源:https://stackoverflow.com/questions/56960677/how-to-implicitly-figure-out-the-type-at-the-head-of-a-shapeless-hlist

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!