Проблема в том, что вы слишком универсальны c:
implicit def memberImplicit[A](
implicit // what you put here is irrelevant
): A = ...
При этом вы в основном предоставили неявное значение для любое значение . Это вступает в противоречие с любым другим неявным определенным вами параметром, а также с любым неявным параметром, который вам нужно получить.
Но давайте спросим, почему компилятор не может доказать, что вы просто не можете предоставить значения, которые вы передаете в memberImplicit
для плохие случаи, и поэтому он не будет рассматривать это как жизнеспособную альтернативу, и, таким образом, он сможет доказать, что эту ветвь деривации следует обрезать (если вы этого не намерены), устранить двусмысленность, а затем исправить.
Дело в том, что тип, который вы возвращаете - A
. Это означает, что даже если вы добавили туда какое-то ограничение, например, например, A =:!= Params
- хотя обычно это будет работать ... вы просто предоставили все эти импликации, поэтому ограничения типов перестали работать, и внезапно производные для таких вещей, как, например, Selector[Params, String]
, имеют больше один из способов быть воплощенным. В этой ситуации практически любая реализация, которую вы попробуете - до тех пор, пока она вернет A
, - потерпит неудачу.
Чтобы все работало, вы ДОЛЖНЫ ограничить вывод тем, что он не будет соответствовать всем - На самом деле, чем меньше совпадений, тем лучше. Например, создайте отдельный класс типов для извлечения значений из HLists:
trait Extractable[A] { def extract(): A }
object Extractable {
implicit def extractHList[H <: HList, A](
implicit
h: H,
selector: Selector[H, A]
): Extractable[A] = () => selector(h)
}
def extract[A](implicit extractable: Extractable[A]): A = extractable.extract()
, а затем
extract[String] // "hello"