有没有一种方法可以从Scala Shapeless中为HList的每个成员派生隐式?
我尝试了以下方法:有没有一种方法可以从Scala Shapeless中为HList的每个成员派生隐式?,scala,implicit,shapeless,Scala,Implicit,Shapeless,我尝试了以下方法: type Params = String :: Int :: HNil implicit val params: Params = "hello" :: 5 :: HNil // Supposed to create an implicit for string and int if needed implicit def meberImplicit[A]( implicit params: Params, selector: Selector[Params
type Params = String :: Int :: HNil
implicit val params: Params = "hello" :: 5 :: HNil
// Supposed to create an implicit for string and int if needed
implicit def meberImplicit[A](
implicit
params: Params,
selector: Selector[Params, A]
): A = params.select[A]
// Summoning a string
implicitly[String] // compile-time error
然而,我得到了一个发散的隐式错误:
diverging implicit expansion for type String
我是不是遗漏了什么?也许已经有了一种内置的或更好的方法来实现这一点?问题是你太过泛化了: 这样,您基本上为任何值提供了隐式。这与您定义的任何其他隐式参数以及需要获取的任何隐式参数冲突
但是,我们要问为什么编译器不能证明你不能提供给坏的情况下传递给<代码>成员隐式< /代码>,因此它不会认为它是一个可行的选择,所以它能够证明这个分支应该被切断(你不打算去那里),歧义被解决,然后是蛋糕。 问题是,您返回的类型是
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()
错误:值提取不是类型参数H的成员
选择器(H.extract())
请立即尝试,我无意中在那里留下了我看到的旧尝试的一行。我一直怀疑它与返回类型有关。谢谢
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"