Mic*_*ier 4 scala implicit shapeless
类型级别foldRight工作正常(getLabelWithValues),后续类型级别map(getValues)也可以正常工作.如果我在一个方法(getValuesFull)中组合两者,它就不再起作用了.丢失的是什么?
完整的源代码(sbt准备好~run使用隐式调试输出)在这里:https://github.com/mpollmeier/shapeless-playground/tree/8170a5b
case class Label[A](name: String)
case class LabelWithValue[A](label: Label[A], value: A)
val label1 = Label[Int]("a")
val labels = label1 :: HNil
object combineLabelWithValue extends Poly2 {
implicit def atLabel[A, B <: HList] = at[Label[A], (B, Map[String, Any])] {
case (label, (acc, values)) ?
(LabelWithValue(label, values(label.name).asInstanceOf[A]) :: acc, values)
}
}
object GetLabelValue extends (LabelWithValue ~> Id) {
def apply[B](labelWithValue: LabelWithValue[B]) = labelWithValue.value
}
val labelsWithValues: LabelWithValue[Int] :: HNil = getLabelWithValues(labels)
// manually mapping it works fine:
val valuesManual: Int :: HNil = labelsWithValues.map(GetLabelValue)
// using a second function with Mapper works fine:
val valuesSecondFn: Int :: HNil = getValues(labelsWithValues)
// error: could not find implicit value for parameter mapper: shapeless.ops.hlist.Mapper.Aux[Main.GetLabelValue.type,WithValues,Values]
// val valuesFull: Int :: HNil = getValuesFull(labels)
def getLabelWithValues[L <: HList, P, WithValues](labels: L)(
implicit folder: RightFolder.Aux[L, (HNil.type, Map[String, Any]), combineLabelWithValue.type, P],
ic: IsComposite.Aux[P, WithValues, _]
): WithValues = {
val state = Map("a" -> 5, "b" -> "five")
val resultTuple = labels.foldRight((HNil, state))(combineLabelWithValue)
ic.head(resultTuple)
}
def getValues[WithValues <: HList, Values <: HList](withValues: WithValues)(
implicit mapper: Mapper.Aux[GetLabelValue.type, WithValues, Values]
): Values = {
withValues.map(GetLabelValue)
}
def getValuesFull[L <: HList, P, WithValues <: HList, Values <: HList](labels: L)(
implicit folder: RightFolder.Aux[L, (HNil.type, Map[String, Any]), combineLabelWithValue.type, P],
ic: IsComposite.Aux[P, WithValues, _],
mapper: Mapper.Aux[GetLabelValue.type, WithValues, Values]
): Values = {
val state = Map("a" -> 5, "b" -> "five")
val resultTuple = labels.foldRight((HNil, state))(combineLabelWithValue)
val withValues: WithValues = ic.head(resultTuple)
withValues.map(GetLabelValue)
}
Run Code Online (Sandbox Code Playgroud)
这里的问题是,你结束了试图映射在一个HList地方的HNil是静态类型的HNil.type.这通常不起作用 - 例如在这样的简化情况下:
import shapeless._, ops.hlist.Mapper
val mapped1 = Mapper[poly.identity.type, HNil]
val mapped2 = Mapper[poly.identity.type, HNil.type]
Run Code Online (Sandbox Code Playgroud)
mapped1会编译,但mapped2不会.
关键是要改变HNil.type你的RightFolder类型HNil,然后调用foldRight用HNil: HNil.这将使一切工作正常.
我还有一些其他的建议(构造元组P代替使用IsComposite,跳过Auxon mapper并返回mapper.Out而不是使用Value类型参数等),但它们可能超出了这个问题的范围.
| 归档时间: |
|
| 查看次数: |
220 次 |
| 最近记录: |