blob: 37bc0958d3e4209587320aeac8ace2c6bd86e7b7 (
plain) (
tree)
|
|
object Sessions {
trait Session {
type Dual <: Session
def run(dp: Dual): Unit
}
sealed case class Stop extends Session {
type Dual = Stop
def run(dp: Dual): Unit = {}
}
// can't write B <: Session{type Dual = BDual} due to limitations in type inference algorithm
// (type variables cannot occur on both sides of <:)
// using B#Dual instead of BDual is too imprecise, since it is disconnected from the actual argument that is passed for B
// would be nice if we could introduce a universal quantification over BDual that is not part of the
// type parameter list
sealed case class In[A, B <: Session, BDual <: Session](recv: A => B)(implicit dual: B <:< Session{type Dual=BDual}) extends Session {
type Dual = Out[A, BDual]
def run(dp: Dual): Unit = recv(dp.data) run dp.cont
}
sealed case class Out[A, B <: Session](data: A, cont: B) extends Session {
type Dual = In[A, cont.Dual, cont.Dual#Dual]
def run(dp: Dual): Unit = cont run dp.recv(data)
}
def addServer =
In{x: Int =>
In{y: Int => System.out.println("Thinking")
Out(x+y,
Stop())}}
def addClient =
Out(3,
Out(4, { System.out.println("Waiting")
In{z: Int => System.out.println(z)
Stop()}}))
def myRun = addServer run addClient
}
|