0__*_*0__ 6 scala type-constraints type-parameter path-dependent-type
我想利用Scala的类型系统来约束系统中的操作,在该系统中存在对某些值的版本化引用.这一切都发生在一些附加Ctx了版本类型的事务上下文中V.现在有一个Factory创建引用变量.它们是通过附加它们的创建版本(类型参数V1)创建的,对应于调用工厂的上下文版本.
现在想象一些代码试图在更高版本中访问该引用,即使用不同的代码Ctx.我想要实现的是禁止Ref在与创建版本不匹配的任何版本(Ctx的V类型字段)中调用访问权限,但允许您通过一些返回新的替换机制来解析引用Ref在当前版本中可以访问的视图.(如果substitute使用无效的上下文调用它是可以的,例如一个比Refs 更旧的V1- 在这种情况下可能抛出运行时异常)
这是我的尝试:
trait Version
trait Ctx {
type V <: Version
}
object Ref {
implicit def access[C <: Ctx, R, T](r: R)(implicit c: C, view: R => Ref[C#V, T]): T =
view(r).access(c)
implicit def substitute[C <: Ctx, T](r: Ref[_ <: Version, T])
(implicit c: C): Ref[C#V, T] = r.substitute(c)
}
trait Ref[V1 <: Version, T] {
def access(implicit c: { type V = V1 }): T // ???
def substitute[C <: Ctx](implicit c: C): Ref[C#V, T]
}
trait Factory {
def makeRef[C <: Ctx, T](init: T)(implicit c: C): Ref[C#V, T]
}
Run Code Online (Sandbox Code Playgroud)
问题是以access整个事物编译的方式定义类方法,即复合对象access应该编译,但同时我不能access用any 调用这个类方法Ctx,只有一个版本与引用版本匹配.
优选地,没有结构类型或任何强加性能问题的东西.
仅供参考,为了结束这个问题,这是我喜欢的另一个想法,因为客户端代码相当混乱:
trait System[A <: Access[_]] {
def in[T](v: Version)(fun: A => T): T
}
trait Access[Repr] {
def version: Version
def meld[R[_]](v: Version)(fun: Repr => Ref[_, R]): R[this.type]
}
trait Version
trait Ref[A, Repr[_]] {
def sub[B](b: B): Repr[B]
}
object MyRef {
def apply[A <: MyAccess](implicit a: A): MyRef[A] = new Impl[A](a)
private class Impl[A](a: A) extends MyRef[A] {
def sub[B](b: B) = new Impl[B](b)
def schnuppi(implicit ev: A <:< MyAccess) = a.gagaism
}
}
trait MyRef[A] extends Ref[A, MyRef] {
// this is how we get MyAccess specific functionality
// in here without getting trapped in more type parameters
// in all the traits
def schnuppi(implicit ev: A <:< MyAccess): Int
}
trait MyAccess extends Access[MyAccess] {
var head: MyRef[this.type]
var tail: MyRef[this.type]
def gagaism: Int
}
def test(sys: System[MyAccess], v0: Version, v1: Version): Unit = {
val v2 = sys.in(v0) { a => a.tail = a.meld(v1)(_.head); a.version }
val a3 = sys.in(v2) { a => a }
val (v4, a4) = sys.in(v1) { a =>
a.head = a.head
println(a.head.schnuppi) // yes!
(a.version, a)
}
// a3.head = a4.head // forbidden
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
347 次 |
| 最近记录: |