另一个隐式方法参数的依赖类型的方法参数 - 是否可能?

时间:2014-05-04 20:06:55

标签: scala

(长篇)插图:

// 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)
  }
}

这是一个完整的工作代码。在这个例子中,我有一个固定的结构化查询的案例层次结构,它需要以某种方式在不同的域上运行。域的公共部分是域特征的一部分。

让我们看一下Query trait中的select定义:它需要一个特定的域(应该是一个稳定的值),以及该域的依赖类型的数据。客户端将特定域和数据传递给select方法。 这是一个方法的示例,其中参数是另一个(非隐式)参数的依赖类型。

我想以某种方式“隐藏”域名,以便只传递数据(隐式传递域名)。但我不能指出它:

  1. 如果我宣布:

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

    编译器抱怨,因为隐式方法参数应该是最后的。

  2. 如果我交换这两个参数:

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

    编译器抱怨使用后定义域名: 非法依赖方法类型:参数出现在同一部分中的另一个参数的类型或更早的

  3. 如何隐式传递域参数?

    更一般地说,是否可以使用另一个隐式方法参数的依赖类型的方法参数?

1 个答案:

答案 0 :(得分: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)