Scala shapeless selection from HList of dependent types 问题

Scala shapeless selection from HList of dependent types problem

我有一个依赖于类型的 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
    }
  }
}

成像有另一个 class 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()

这不会编译,因为 g 没有出现在 HList 中:

g.simplePrint()

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

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

有什么方法可以正确指定选择器类型吗?

没有办法在CfOps(ecf)中推断N具体ecf: C,所以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