#scala #generics #typeclass #implicit #shapeless
#scala #общие #класс типов #неявный #бесформенный
Вопрос:
Я пытаюсь включить немного shapeless в свой код и сталкиваюсь с досадно ранним препятствием. В приведенном ниже примере кажется, что HCON-добавление неопределенного объекта в HNil:
trait HasValue[A, B] {
def get(a: A): B
def getAll[L <: HList, O <: HList](a: A)(implicit ga: GetAll[A, L]): O = ga.getAll(a, HNil)
}
trait GetAll[A, B] {
def getAll[L <: HList, O <: HList](a: A, l: L): O
}
implicit def getAllIfHasValue[A, B](implicit ev: HasValue[A, B]) = new GetAll[A, B] {
def getAll[L <: HList, O <: HList](a: A, l: L): O = ev.get(a) :: l
}
и получение ошибки — type mismatch: Found B :: L, Required O
.
Я бы подумал, что, поскольку L
сам является an HList
, B :: L
сам должен быть an HList
, и поэтому все должно быть хорошо. Но, очевидно, нет.
Любая помощь приветствуется!
Комментарии:
1. Неясно, чего вы пытаетесь достичь.
getAll
подпись выглядит подозрительно: в ней говорится, что для каждого типа списка HListL
иO
вы можете создаватьO
только на основеL
иA
. Эта функция не имеет разумных реализаций (кроме возвратаHNil
always). Возможно, вы захотите перейтиL
иO
к списку параметров типа признака.2. @simpadjo — Да — я не использовал здесь хороший пример. Одна вещь, которая немного сбила меня с толку в примерах, которые я читал, заключалась в том, что люди склонны использовать синтаксис (при использовании HList в качестве аргументов функции или возвращаемых типов), скажем,
def f[L <: HList]: L = 1 :: HNil
. Для меня не сразу очевидно, зачемL
здесь нужен параметр type. Почему не простоdef f: HList = 1 :: HNil
?3.
HList
тип ничего не говорит о типах его элемента.L
предполагается, что он также содержит информацию об элементах.4. @Chrisper, кстати,
def f[L <: HList]: L = 1 :: HNil
неверно. Это как если бы я написалdef f[A]: A = 1
. Я думаю, вам следует подумать, что означают параметры типа в Scala.5. @Chrisper Если вы пишете, у которого
1 :: HNil
есть типHList
, вы теряете информацию об уровне типаInt :: HNil
.HList
не лучше, чемList[Any]
.
Ответ №1:
Я думаю, ошибка довольно ясна
type mismatch;
found : B :: L
required: O
ev.get(a) :: l
имеет тип B :: L
, но O
ожидается.
Я бы подумал, что, поскольку
L
сам является anHList
,B :: L
сам должен быть anHList
, и поэтому все должно быть хорошо.
B :: L
действительно HList
, это an . Проблема в том, что B :: L
это не O
так .
И когда вы пишете подпись
def getAll[L <: HList, O <: HList](a: A, l: L): O = ???
это означает, что для любого типа L <: HList
и любого типа O <: HList
, имеющего значения a: A
и l: L
производящего значение типа O
. Я думаю, это не то, что вы хотели.
Может быть, вы хотели вернуть тип O
в зависимости от типов A
, B
. Затем вы можете ввести параметр типа
trait GetAll[A, B] {
type O
def getAll[L <: HList](a: A, l: L): O
}
Или, может быть, вы хотели вернуть тип O
в зависимости от типов A
, B
, L <: HList
. Тогда дополнительно вам следует перейти L
на уровень признака
trait GetAll[A, B, L <: HList] {
type O
def getAll(a: A, l: L): O
}
Комментарии:
1. спасибо — да, я думаю, у меня возникла некоторая путаница в отношении того, как параметры типа работают в таких контекстах. Основная проблема (которую мой первоначальный пример был плохим представлением), которую я теперь выяснил.