(long) illustration:
trait Domain {
type Data
type IntData <: Data
type PairData <: Data
def select(query: Query, data: Data): Data = ???
}
sealed trait Query {
def select[D <: Domain](domain: D)(data: domain.Data): domain.Data =
domain.select(this, data)
}
case object IdQuery extends Query
case class SuccQuery(val q: Query) extends Query
object Values extends Domain {
sealed abstract class Data
case class IntData(val data: Int) extends Data
case class PairData(val a: Data, val b: Data) extends Data
}
object Paths extends Domain {
}
object Test {
def test {
val query: Query = ???
val value: Values.Data = ???
val path: Paths.Data = ???
val valueResult = query.select(Values)(value)
val pathResult = query.select(Paths)(path)
}
}
This is full working code. In the example, I have a fixed case hierarchy of structured queries that must somehow work on different domains. The common parts of domains are part of the Domain property.
Look at the definition of select in the Query trait: it takes a specific domain (which should be a stable value) and data of the dependent type of that domain. The client transfers both a specific domain and data to the selection method. This is an example of a method in which a parameter has a dependent type of another (implicit) parameter.
I want to somehow "hide" the domain, so that only data is transferred (the domain is passed implicitly). But I can not nail him:
, ?
, ?