gpt4 book ai didi

隐式 def 中的 Scala 高级类型失败,错误为 "could not find implicit value"

转载 作者:行者123 更新时间:2023-12-04 06:56:41 24 4
gpt4 key购买 nike

我正在使用隐式 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, L2 <: HList, R <: HList](implicit f: Appender[L1, L2, R]): Appender[HCons[T, L1], L2, HCons[T, R]] = {
Appender[HCons[T, L1], L2, HCons[T, R]]((l1: HCons[T, L1], 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, U <: HList](head: T, tail: U) extends HList {
type Plus[L <: HList] = HCons[T, U#Plus[L]]

def ::[V](v: V) = HCons(v, this)

def ++[L2 <: HList](l2: L2) = HList.++(this,l2)
}

我收到此编译错误:
could not find implicit value for parameter f: Appender[HCons[T,U],L2,HCons[T,U]#Plus[L2]]

HConsHList 的子类型,就像 HList.++ 定义的 L1 类型一样,我以为还可以。

我试过这个,但效果不佳:
implicit def consAppender[T, L1 <: HList, L2 <: HList, L3, R <: HList](implicit f: Appender[L1, L2, R], ev: L3 <:< HCons[T, L1]): Appender[HCons[T, L1], L2, HCons[T, R]] = {
Appender[HCons[T, L1], L2, HCons[T, R]]((l1: L3, l2: L2) => HCons(l1.head, f(l1.tail, l2)))
}

我错过了什么?

谢谢 :)

最佳答案

您应该更改您的 ++方法定义来自:

 def ++[L2 <: HList](l2: L2) = HList.++(this,l2)

对此:
def ++[L2 <: HList](l2: L2)(implicit f: Appender[HCons[T,U], L2, 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, U], L2, HCons[T, U#Plus[L2]]] .编译器可以从 HList.consAppender 填充这个隐式参数,但这又需要另一个类型为 Appender[U, L2, U#Plus[L2]] 的隐式参数.这是编译器自己无法发现的参数。知道了这一点,上面的代码可以简化为:
def ++[L2 <: HList](l2: L2)(implicit f: Appender[U, L2, U#Plus[L2]]): Plus[L2] = HList.++(this, l2)

更新 2:编译器必须在调用站点填写隐式参数,在我们的例子中是在 HCons.++ 中。方法(可以验证,例如,使用 scalac -Xprint:typer )。它可以从提供两种 appender 类型的隐式中进行选择:
Appender[HNil, L, L]
Appender[HCons[T, L1], L2, HCons[T, R]]

第一个只能在类型参数 U 时使用是 HNil ,其他只有当 UHCons .但是这个信息在 HCons.++里面是没有的.它只知道 U <: HList但不知道 HList 的哪个实现它是,因此失败。

关于隐式 def 中的 Scala 高级类型失败,错误为 "could not find implicit value",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36945476/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com