scala - 使用 Shapeless Polyfil 在记录上进行一般映射

标签 scala generics shapeless

类似于这里的这个问题( Mapping over Shapeless record ),我试图映射一个简单的无形状记录(在这种情况下,如果我遇到 Int 类型的值,我想将其转换到Double)。

object Main extends App {
  import shapeless._ ; import syntax.singleton._ ; import record._
  import ops.record._
  import syntax.singleton._

  case class S(int:Int,t:String)

  val s = S(3,"a")

  val gen = LabelledGeneric[S]

  val rec = gen.to(s)

  val extended = rec + ('inPrint ->> true)

  val removed = rec - 'int

  val keys = Keys[gen.Repr]

  val options = 
    ('awesomeString ->> "a") ::
    ('epicInt ->> 5:Int) ::
    HNil

  def intToDouble(i:Int):Double = i.toDouble

  object bind extends FieldPoly {
    implicit def rpb[T, K](implicit witness: Witness.Aux[K]): Case.Aux[
      FieldType[K, Int],
      FieldType[K, Double]
      ] = atField(witness)(intToDouble)
  }

  val z = options.map(bind)

}

但是,当我尝试编译时,出现以下错误

could not find implicit value for parameter mapper: shapeless.ops.hlist.Mapper[Main.bind.type,shapeless.::[String with shapeless.record.KeyTag[Symbol with shapeless.tag.Tagged[String("awesomeString")],String],shapeless.::[Int,shapeless.HNil]]]

我是否遗漏了一些重要的东西?

最佳答案

您的示例有一个非常小的问题。你有,

val options = 
  ('awesomeString ->> "a") ::
  ('epicInt ->> 5:Int) ::
  HNil

如果您将其粘贴到 REPL 中,您会发现您已经忘记了 'epicInt键入记录的最后一个元素。这是因为类型归属的绑定(bind)不如 ->> 紧密。运算符,因此实际上您首先用它的键标记了您的值,然后立即再次将其丢弃。这将为您留下有效的 HList ,但不幸的是,没有一个适合成为唱片的形状。解决方法是完全删除类型归属,或使用括号(即 (5: Int)

更大的问题是您使用FieldPoly这里。 FieldPoly适用于您要操作的 key 静态已知的情况。这里的情况并非如此:类型变量 K是免费的并且必须被推断。不幸的是,这是不可能的:它必须从 atField 的第一个参数推断出来。但这又取决于K通过 witness 的隐式定义.

可能是 FieldPoly 的不同变体更适合您的场景将会很有用。与此同时,一个普通的Poly1对整个字段(即键与值相结合)进行操作将执行您想要的操作,

trait bind0 extends Poly1 {
  implicit def default[E] = at[E](identity) // default case for non-Int fields
}

object bind extends bind0 {
  implicit def caseInt[K] =                 // case for fields with Int values 
    at[FieldType[K, Int]](field[K](intToDouble _))
}

关于scala - 使用 Shapeless Polyfil 在记录上进行一般映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26751711/

相关文章:

java - 我的 scala 应用程序中 val、lazy val 和 def 的神秘行为以及隐式转换

scala - 在 Scalaz 中将 Free 与非仿函数一起使用

scala - 来自 Scala 和 Guava 的 Murmur3 的不同结果

java - 如何在泛型类中返回对象的泛型类型?

scala - 将 List[OF[C]] 转换为 F[B],其中案例类 B 的类型与 A 对齐

scala - 可以在 Scala HList 上执行 Map 吗

scala - 比较 Option[T] 的实例,避免 None == None

c# - C# 泛型方法中的 "where T : class"是什么?

c# - 在 C# 中不使用参数将信息传递给构造函数

scala - 如何定义一个 HList 类型,但基于另一个 HList 类型