我有DL <: HList
,我正试图在mkString
上使用detailsIn: DL
:
val detail: String = detailsIn.mkString("", "; ", "")
mkString
在Shapeless中定义如下:
def mkString(start: String, sep: String, end: String)
(implicit toTraversable: ToTraversable.Aux[L, List, Any]): String = this.toList.mkString(start, sep, end)
我已经看到一些例子定义了一个需要ToTraversable暗示的函数,但是还没有看到任何人真正创造它的价值(我怀疑我在Shapeless中不够精通以便很容易找到这些东西因为我应该能够)。
我有以下片段,我需要填写???
,如果这是正确的,我认为一个例子会非常有用:
implicit val dlToList: ToList[DL, Any] = new ToTraversable[DL, List] {???}
但是,我怀疑可能有工厂方法可以做到这一点,但如果是这样,我还没有找到它。
答案 0 :(得分:3)
您不应该自己实例化此值。相反,你应该要求它作为一个额外的隐式参数,并让编译器完成工作:
def myMethod[DL <: HList](detailsIn: DL)(implicit ev: ToTraversable.Aux[DL, List, Any]) = {
val detail: String = detailsIn.mkString("", "; ", "")
println(detail)
}
修改强>:
如果myMethod可以找到隐含的,为什么mkString找不到呢?
因为从myMethod
的角度来看,您正在为任何ToTraversable[DL, List]
寻找DL <: HList
!编译器无法弄清楚对于DL
的每个可能实例,都可以导出ToTraversable
(即使在这种特殊情况下,结构归纳可能也是如此)。
相反,实际进行调用的地方myMethod(1 :: "s" :: HNil)
应该具有隐式解析ToTraversable.Aux[Int :: String :: HNil, List, Any]
的所有静态信息。但是你可能会问,如果我不想在通用语境中调用myMethod
怎么办?然后你别无选择,只能在调用链中进一步传播隐式约束,直到所有通用性都消失为止。