A method parameter of a dependent type of another parameter of an implicit method - is this possible?

(long) illustration:

// Base trait for different domains. Domains hold value-like things, 
// which have some known relationships between them.
trait Domain {
  type Data
  type IntData <: Data
  type PairData <: Data

  def select(query: Query, data: Data): Data = ???
}

// Base trait for queries. Queries operate in a 
    // specific (but arbitrary) domain.
sealed trait Query {
  def select[D <: Domain](domain: D)(data: domain.Data): domain.Data =
    domain.select(this, data)
}

// Specific queries
case object IdQuery extends Query
case class SuccQuery(val q: Query) extends Query
// ...

// Specific domains
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:

  • If I declare:

    def select[D <: Domain](implicit domain: D)(data: domain.Data)
    

    , .

  • :

    def select[D <: Domain](data: domain.Data)(implicit domain: D)
    

    : :

, ?

, ?

+4
1

:

def select[D <: Domain](implicit domain: D) =
    new Selector[D](domain)

class Selector[D <: Domain](domain: D) {
   def data(data: domain.Data): domain.Data = ???
}

select.data(someData)
+1

Source: https://habr.com/ru/post/1539191/


All Articles