隐式def中的Scala更高级别的类型失败,“无法找到隐含值”
我正在使用隐式def来构建递归HList类型,以匹配几种更高级别的HList类型.我受到
this post的启发.
这段代码非常完美: sealed trait HList { type Plus[L <: HList] <: HList } class HNil extends HList { type Plus[L <: HList] = L def ::[T](v: T) = HCons(v,this) } case class Appender[L1 <: HList,L2 <: HList,R <: HList](fn: (L1,L2) => R) { def apply(l1: L1,l2: L2) = fn(l1,l2) } object HNil extends HNil object HList { def ++[L1 <: HList,L2 <: HList](l1: L1,l2: L2)(implicit f: Appender[L1,L2,L1#Plus[L2]]): L1#Plus[L2] = f(l1,l2) implicit def nilAppender[L <: HList]: Appender[HNil,L,L] = Appender((v: HNil,l: L) => l) implicit def consAppender[T,L1 <: HList,R <: HList](implicit f: Appender[L1,R]): Appender[HCons[T,L1],HCons[T,R]] = { Appender[HCons[T,R]]((l1: HCons[T,l2: L2) => HCons(l1.head,f(l1.tail,l2))) } } case class HCons[T,U <: HList](head: T,tail: U) extends HList { type Plus[L <: HList] = HCons[T,U#Plus[L]] def ::[V](v: V) = HCons(v,this) } import HList._ val hlist1 = 2.0 :: "hi" :: HNil val hlist2 = 1 :: HNil val sum = ++(hlist1,hlist2) println("last element : " : + sum.tail.tail.head) // prints last element : 1" 现在,我不知道为什么,但是如果我尝试在HCons上添加一个方法,它只是调用现有的HList.方法,这是行不通的: case class HCons[T,tail: U) extends HList { type Plus[L <: HList] = HCons[T,this) def ++[L2 <: HList](l2: L2) = HList.++(this,l2) } 我得到这个编译错误: could not find implicit value for parameter f: Appender[HCons[T,U],U]#Plus[L2]] 由于HCons是HList的子类型,如HList定义的L1类型.,我觉得没关系. 我试过这个但是效果不好: implicit def consAppender[T,L3,R],ev: L3 <:< HCons[T,L1]): Appender[HCons[T,R]]((l1: L3,l2))) } 我错过了什么? 谢谢 :) 解决方法
您应该从以下方法更改方法定义:
def ++[L2 <: HList](l2: L2) = HList.++(this,l2) 对此: def ++[L2 <: HList](l2: L2)(implicit f: Appender[HCons[T,Plus[L2]]) = HList.++(this,l2) 编译器没有足够的信息来在方法定义中选择正确的隐式值,但是当您从外部传递appender时,此示例应该传递: val hlist1 = 2.0 :: "hi" :: HNil val hlist2 = 1 :: HNil println(hlist1++hlist2) 更新1:在HCons的方法中,我们调用HList.需要隐式参数的方法.此参数必须是Appender [HCons [T,HCons [T,U#Plus [L2]]]类型.编译器可以从HList.consAppender填充这个隐式参数,但这又需要另一个Appender [U,U#Plus [L2]]类型的隐式参数.这是编译器无法发现的参数.知道了这一点,上面的代码可以简化为: def ++[L2 <: HList](l2: L2)(implicit f: Appender[U,U#Plus[L2]]): Plus[L2] = HList.++(this,l2) 更新2:编译器必须在呼叫站点填写隐式参数,在我们的情况下在HCons中填写.方法(可以用例如scalac -Xprint:typer验证).它可以选择提供两种appender类型的implicits: Appender[HNil,L] Appender[HCons[T,R]] 第一个只能在类型参数U是HNil时使用,另一个只在U是HCons时使用.但这些信息在HCons内部无法获得. .它只知道U<:HList,但不知道HList的哪个实现,因此失败. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |