Функция, которая извлекает элемент из HList (сохраняя его тип) - PullRequest
0 голосов
/ 20 ноября 2018

У меня есть этот тип, который будет сгенерирован с помощью бесформенного:

type hlistt = STUDENT.type :: AUTO_LOANS.type :: HNil

В основном у меня есть куча объектов case, расширяющих черту, поэтому мне удалось создать метод, который дает мне экземпляры всех объектов case какHList

Затем, используя import shapeless.ops.hlist.Last и init, я написал метод для получения одного из узлов в HList, если значение равно строке "student":

def getLast(hl:hlistt) = {
  val last0=Last[hlistt]
  val la=last0(hl)

  if (la.value == "student") la
  else init(hl)
}

Проблема в том, что если я вызову этот метод, я не получу правильный тип узла из HList.

getLast(STUDENT :: AUTO_LOANS :: HNil)

Метод работает и возвращает узел, но тип отключен:

Product with Serializable = STUDENT :: HNil

Нужны ли мне какие-либо косвенные выражения Witness / Aux для возврата правильного типа?

Ответы [ 2 ]

0 голосов
/ 20 ноября 2018

la относится к типу AUTO_LOANS.type, init(hl) относится к типу STUDENT.type :: HNil, поэтому

if (la.value == "student") la
else init(hl)

относится к типу Any (или Product with Serializable).

Если вы хотите вернуть значения разных типов из разных веток, вам нужен Poly.

import shapeless.{Poly1, Witness}

object myPoly extends Poly1 {
  implicit def studentCase: Case.Aux[Witness.`"student"`.T, STUDENT.type] = 
    at(_ => STUDENT)
  implicit def autoLoansCase: Case.Aux[Witness.`"auto-loans"`.T, AUTO_LOANS.type] = 
    at(_ => AUTO_LOANS)
}

import shapeless.syntax.singleton._
println(
  myPoly("student".narrow)
) // STUDENT

println(
  myPoly("auto-loans".narrow)
) // AUTO_LOANS

// println(
//   myPoly("abc".narrow)
// )  // doesn't compile

Этот подход работает, если строка известна во время компиляции.

0 голосов
/ 20 ноября 2018

Я не совсем уверен, что вы хотите сделать.Дано:

type hlistt = STUDENT.type :: AUTO_LOANS.type :: HNil

Last[hlistt] разрешится до AUTO_LOANS.type (ваша ветвь true, если), в то время как init разрешится до STUDENT :: HNil (ваша ветвь if, если)

LUB.(наименьшая верхняя граница) этих типов будет Product with Serializable, поэтому вы видите это.

Если вы хотите проверить свойство среды выполнения члена hlist, вам нужно будет пропустить соответствующие границы типов и типы результатов, выведя их с помощью соответствующего механизма.В этом случае это уже задано бесформенным.

https://scalafiddle.io/sf/fdtn3cz/0

Это то, что вы хотели?

РЕДАКТИРОВАТЬ: Я также просто прочитал

У меня есть этот тип, который будет генерироваться динамически:

что вы подразумеваете под «динамически»?потому что, если вы не можете указать некоторые свойства времени компиляции, бесформенное может не быть решением, которое вы ищете.

...