Бесформенная заливка HList в зависимости от длины шрифта - PullRequest
0 голосов
/ 18 октября 2019

Работая с HList с опциями, я пытаюсь сгенерировать HList со всеми элементами, равными None. Однако существует проблема с неявным разрешением объекта Fill.

Функция natLength вытекает из этого ответа SO: Длина пареметра типа HList в терминах Nat .

type OL = Option[Double] :: Option[Int] :: Option[String] :: HNil


def emptyList[T <: HList: *->*[Option]#λ](length: Nat)(
  implicit fill: Fill.Aux[length.N, None.type, T]
): T = {
  HList.fill(length)(None)
}

def natLength[T <: HList](implicit length: Length[T]): length.Out = length()

emptyList[OL](natLength[OL])

Приведенный выше код позволяет компилятору завершиться с ошибкой:

could not find implicit value for parameter fill: 
shapeless.ops.hlist.Fill[shapeless.Succ[shapeless.Succ[shapeless.Succ[shapeless._0]]],None.type]{type Out = Option[Double] :: Option[Int] :: Option[String] :: shapeless.HNil}

Возможно ли то, что я пытаюсь достичь? Генерация HList только на основе длины его типа?

1 Ответ

2 голосов
/ 18 октября 2019

Стандартный способ отладки последствий - попытаться разрешить их вручную (явным образом) и посмотреть на ошибки компиляции.

emptyList[OL](natLength[OL])(
  implicitly[*->*[Option]#λ[Option[Double] :: Option[Int] :: Option[String] :: HNil]],
  implicitly[Fill.Aux[_3, None.type, None.type :: None.type :: None.type :: HNil]],
)

производит

Error: type mismatch;
 found   : shapeless.ops.hlist.Fill[shapeless.nat._3,None.type]{type Out = None.type :: None.type :: None.type :: shapeless.HNil}
    (which expands to)  shapeless.ops.hlist.Fill[shapeless.Succ[shapeless.Succ[shapeless.Succ[shapeless._0]]],None.type]{type Out = None.type :: None.type :: None.type :: shapeless.HNil}
 required: shapeless.ops.hlist.Fill[shapeless.Succ[shapeless.Succ[shapeless.Succ[shapeless._0]]],None.type]{type Out = Option[Double] :: Option[Int] :: Option[String] :: shapeless.HNil}
    implicitly[Fill.Aux[_3, None.type, None.type :: None.type :: None.type :: HNil]],

Что должно быть T вdef emptyList[T <: HList: *->*[Option]#λ]...? Это Option[Double] :: Option[Int] :: Option[String] :: HNil? Тогда почему вы запрашиваете неявный Fill.Aux[length.N, None.type, T] с Out -типом того же T, тогда как он должен быть None.type :: None.type :: None.type :: HNil.

Попробуйте

def emptyList(length: Nat)(
  implicit fill: Fill[length.N, None.type]
): fill.Out = {
  HList.fill(length)(None)
}

emptyList(natLength[OL]) //None :: None :: None :: HNil

*->*[Option]#λконтекст связан в def natLength.

...