从依赖类型的HList中选择Scala无形状问题



我有一个类型相关的Cf类型,它存储单调字符串:

trait Cf {
type Name <: String with Singleton
def value: Name
}
object Cf {
type Aux[A <: String with Singleton] = Cf { type Name = A }

def apply(name: String): Aux[name.type] = { 
val w = name.witness
new Cf {
override type Name = w.T
override def value: Name = w.value
}
}
}

具有另一个类 Dbtest 的映像,该类仅存储某些 HList 类型的列:

class Dbtest[T <: HList](val columns: T)

然后我想为我的 Cf 类型编写一些扩展方法,但有一个问题:将调用扩展方法的实例的类型必须在 Dbtest 实例的 HList 中呈现:

object Ops {
implicit class CfOps[C, N <: String with Singleton, T <: HList](ecf: C)
(
implicit 
db: Dbtest[T]
, ev: C =:= Cf.Aux[N]
, selector: Selector[T, C]
) {
private val cf = selector(db.columns)
def simplePrint(): Unit = println(cf.value)
}
}

创建 Cf 和 Dbtest 实例的实例,其中包含其中一些实例:

object Test extends App {
val c = Cf("c")
val b = Cf("b")
val g = Cf("g")
implicit val db = new Dbtest(c :: b :: HNil)
...

我希望编译它,因为 HList 中指定了c

c.simplePrint()

这不是编译,因为 HList 中没有g

g.simplePrint()

主要问题是 - 我无法正确指定隐式选择器类型,因此编译器看不到我的simplePrint()方法:

value simplePrint is not a member of Cf{type Name = String("c")}

有没有办法正确指定选择器类型?

没有办法在CfOps(ecf)中推断出特定ecf: CN,所以N只是一些抽象类型,没有隐含的证据C =:= Cf.Aux[N]

尝试将CfOps的定义替换为

implicit class CfOps[N <: String with Singleton, T <: HList](ecf: Cf.Aux[N])(
implicit
db: Dbtest[T],
selector: Selector[T, Cf.Aux[N]]
) {
private val cf = selector(db.columns)
def simplePrint(): Unit = println(cf.value)
}

然后

import Ops._
c.simplePrint() // compiles
//g.simplePrint() // doesn't compile

最新更新