加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

隐式def中的Scala更高级别的类型失败,“无法找到隐含值”

发布时间:2020-12-16 08:58:53 所属栏目:安全 来源:网络整理
导读:我正在使用隐式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,t
我正在使用隐式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的哪个实现,因此失败.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读