给定一个由
下面的代码可以工作,但它非常非常hacky,因为它使用了全局变量。相反,我想将
这里是GetLabelWithValue的另一种实现方式,其行为与原版相同:
Label[A](String)
组成的HList,我想将其映射为由LabelWithValue[A](Label[A], A)
组成的HList,实际值来自于Map[String, Any]
。在下面的示例中,我只是在方法中定义了一个值的映射,想象一下这些值来自于数据库。下面的代码可以工作,但它非常非常hacky,因为它使用了全局变量。相反,我想将
Map[String, Any]
传递到GetLabelWithValue
中。然而我没有找到一种方法,因为getValues
的调用者隐式地创建了一个Mapper,在那个时刻值的映射还不存在。我试图自己创建一个Mapper,但我的类型级别编程技能还不够好。import shapeless._
import shapeless.poly._
import shapeless.ops.hlist._
object Main extends App {
case class Label[A](name: String)
case class LabelWithValue[A](label: Label[A], value: A)
// TODO: avoid the horrible global state - pass in the Map as a parameter
var horribleGlobalState: Map[String, Any] = _
object GetLabelWithValue extends (Label ~> LabelWithValue) {
def apply[A](label: Label[A]) =
LabelWithValue(label, horribleGlobalState.get(label.name).asInstanceOf[A])
}
val label1 = Label[Int]("a")
val label2 = Label[String]("b")
val labels = label1 :: label2 :: HNil
val labelsWithValues: LabelWithValue[Int] :: LabelWithValue[String] :: HNil = getValues(labels)
println(labelsWithValues)
def getValues[L <: HList, M <: HList](labels: L)(
implicit mapper: Mapper.Aux[GetLabelWithValue.type, L, M]) = {
horribleGlobalState = Map("a" -> 5, "b" -> "five")
labels map GetLabelWithValue
}
}
这里是GetLabelWithValue的另一种实现方式,其行为与原版相同:
object GetLabelWithValue extends Poly1 {
implicit def caseLabel[A] = at[Label[A]] { label ⇒
LabelWithValue(label, horribleGlobalState.get(label.name).asInstanceOf[A])
}
}