Shapeless HList map после сгибаRight

Уровень типа 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)
}

person Michael Pollmeier    schedule 22.10.2015    source источник
comment
Кстати. Я понимаю, что у меня не будет проблем, если я полностью избавлюсь от LabelWithValue - я просто хотел бы понять, как я могу составить типичную сложность и сопоставить ...   -  person Michael Pollmeier    schedule 23.10.2015


Ответы (1)


Проблема здесь в том, что вы в конечном итоге пытаетесь сопоставить 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.type в ваших RightFolder типах на HNil, а затем вызвать foldRight с HNil: HNil. Это заставит все работать нормально.

Я бы сделал еще несколько предложений (деструктурируйте кортеж вместо P вместо использования IsComposite, пропустите Aux на mapper и верните mapper.Out вместо параметра типа Value и т. Д.), Но они, вероятно, вышли из строя. объем этого вопроса.

person Travis Brown    schedule 23.10.2015
comment
Это было здорово, это знать. И да, всегда полезно уменьшить количество параметров типа. Спасибо! - person Michael Pollmeier; 24.10.2015
comment
Повторите ваши дополнительные предложения: я пробовал и то, и другое раньше, но безуспешно. Я создал следующий вопрос для деструктуризации кортежа: stackoverflow.com/questions/33313164/ - person Michael Pollmeier; 24.10.2015
comment
Кстати. пропуск параметра типа Aux и Value также не работает, но я предполагаю, что это связано с моей правой папкой, поскольку она отлично работает в более простом случае (например, с Tupler). - person Michael Pollmeier; 24.10.2015