簡體   English   中英

foldRight后的無形HList地圖

[英]Shapeless HList map after foldRight

類型級別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)
}

這里的問題是你最終試圖映射HList ,其中HNil被靜態類型化為HNil.type 這通常不起作用 - 例如在這樣的簡化情況下:

import shapeless._, ops.hlist.Mapper

val mapped1 = Mapper[poly.identity.type, HNil]
val mapped2 = Mapper[poly.identity.type, HNil.type]

mapped1將編譯,但mapped2不會。

關鍵是要改變HNil.typeRightFolder類型HNil ,然后調用foldRightHNil: HNil 這將使一切工作正常。

還有一些其他的建議( IsComposite元組代替P而不是使用IsComposite ,跳過mapper上的Aux並返回mapper.Out而不是具有Value類型參數等),但它們可能是超出了這個問題的范圍。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM