I have a type dependent Cf type which stores singletoned string:
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
}
}
}
Imaging having another class Dbtest which only stores columns of some HList type:
class Dbtest[T <: HList](val columns: T)
Then I wanted to write some extension methods for my Cf type but there is one restiction: type of the instance on which extension method is going to be called have to be presented in HList of Dbtest instance :
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)
}
}
Creating instances of Cf and Dbtest instance with some of them inside:
object Test extends App {
val c = Cf("c")
val b = Cf("b")
val g = Cf("g")
implicit val db = new Dbtest(c :: b :: HNil)
...
I want this to compile because c
was specified in the HList:
c.simplePrint()
And this not to compile because g
is not presented in the HList:
g.simplePrint()
Main problem is - I cannot specify implicit Selector type correctly, so my simplePrint()
method is not seen by the compiler:
value simplePrint is not a member of Cf{type Name = String("c")}
Is there a way I can specify selector type correctly?
There is no way to infer N
in CfOps(ecf)
for specific ecf: C
, so N
is just some abstract type and there is no implicit evidence C =:= Cf.Aux[N]
.
Try to replace definition of CfOps
with
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)
}
Then
import Ops._
c.simplePrint() // compiles
//g.simplePrint() // doesn't compile