Preventing unwanted combinations using path-dependent types?

左心房为你撑大大i 提交于 2019-12-08 05:57:22

问题


Major edit to better reflect my intent:

// this *must* be outside of Team
class Player

class Team(val p1: Player, val p2: Player) {
  type P = ??? // <-- what to put here ? see below ...

  // perhaps I can somehow construct a union type:
  // type P = p1.type union p2.type  
  // or perhaps the following :
  // type P = Either[p1.type,p2.type] 
  // The purpose of `P` here is to define a type which can only hold p1 or p2 for values. 

  def position(p: P) = p match {
    case `p1` => 1
    case `p2` => 2
    // Gotcha ! we never get here (=exactly what I want to enforce) if I can get the `P` right ! 
  }
}

val p1=new Player
val p2=new Player
val someP = new Player
val t= new Team(p1,p2)
t.position(t.p1) // allowed
t.position(t.p2) // allowed
t.position(p1) // allowed, since p1 is the same thing as t.p1, or is it ?!
t.position(p2) // allowed, since p2 is the same thing as t.p2, or is it ?!
t.position(someP) // I want this to *not* type-check : Required t.P, Found Player

The Original snippet is here:

// this *must* be outside of Team
class Player

class Team(p1: Player, p2: Player) {
  def position(p: Player) = p match {
    case `p1` => 1
    case `p2` => 2
    // Ah-oh !! is it possible to prevent this using (probably path-dependent) types ? 
  } 
}

val p1=new Player
val p2=new Player
val someP = new Player
val t= new Team(p1,p2)
t.position(p1) // allowed
t.position(p2) // allowed
t.position(someP) // I want this to *not* type-check with an error like "Required: t.Player, Found: Player"

回答1:


This might be a bit overkill, but it solves your problem

class Team(p1: Player, p2: Player) {
  case class Membership(player: Player)

  def position(m: Membership) = m.player match {
    case `p1` => 1
    case `p2` => 2
    // Ah-oh !! is it possible to prevent this using (probably path-dependent) types ? 
  }
}

class Player

val p1 = new Player
val p2 = new Player
val someP = new Player

val t = new Team(p1, p2)
val someT = new Team(someP, someP)

val m1 = t.Membership(p1)
val m2 = t.Membership(p2)
val someM = someT.Membership(someP)

t.position(m1) // allowed
t.position(m2) // allowed
t.position(someM) // This doesn't compile
//type mismatch;  found   : Test.someT.Membership  required: Test.t.Membership


来源:https://stackoverflow.com/questions/35558342/preventing-unwanted-combinations-using-path-dependent-types

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!