定义一个方法,其返回类型是该方法的参数的单例类型

时间:2011-04-07 00:57:01

标签: scala types singleton

仍在与this.types(单身人士类型)挣扎。假设这种情况:

trait Sys[A <: Access] {
  def in[T](v: String): AccessPrepare[A]
}

trait AccessPrepare[A <: Access] {
  val a: A
  def apply[T](fun: a.type => T): T
}

object Ref {
  def single[A <: Access, V](v: V)(implicit a: A): Ref[A, V] = ???
}
trait Ref[A, V]

trait Access {
  def set(r: Ref[this.type, Int]): Unit
}

以下失败:

def test(sys: Sys[Access]): Unit =
  sys.in("v1") { implicit a =>
    val r = Ref.single(44)
    a.set(r)
  }

因为r显然是Ref[Access, Int]类型,而不是Ref[a.type, Int]。我猜是问题是我需要像

这样的一行
def single[A <: Access, V](v: V)(implicit a: A): Ref[a.type, V] = ...

由于“非法依赖方法类型”而未编译...

我有什么想法可以解决这个问题。需求是我没有明确地使用类型注释调用。也就是说,出于可理解的原因,我想写Ref.single[a.type, Int](44)(a)


修改

作为澄清,参考线程Constraining an operation by matching a type parameter to an argument's path-dependent type中的回答“FYI,并关闭问题” - 我想要的另外一点是创建对象(Refs)的可能性不是通过使用访问中的工厂方法但在某处外部(例如,使用new语句)。由于系统不受Access定义的限制,我必须能够使用更多对象扩展它。

1 个答案:

答案 0 :(得分:1)

你有几种可能性。使用Scala 2.8 / 2.8.1,您可以使用私有选项-Ydependent-method-types,然后使用

解决方案
def single[ A <: Access, V ]( v: V )( implicit a: A ) : Ref[ a.type, V ] = // ...

编译好。

如果您想避免依赖方法类型,因为它是私有选项,您仍然可以通过明确键入对Ref.single的调用来编译您的第一个提案:

  val r = Ref.single[a.type, Int](44)

但是,您需要指定类型,因为从不推断单例类型。您的问题与不推断单例类型的问题不同,但与之相关:请参阅How to correctly type-annotate this HList?