Conclusion of result type in continuation

Is it possible to remove some types from the following code:

import util.continuations._ object TrackingTest extends App { implicit def trackable(x: Int) = new { def tracked[R] = shift { cf: (Int => (R, Set[Int])) => cf(x) match { case (r, ints) => (r, ints + x) } } } def track[R](body: => R @cpsParam[(R, Set[Int]), (R, Set[Int])]) = reset { (body, Set[Int]()) } val result = track(7.tracked[Int] + 35.tracked[Int]) assert(result == (42, Set(7, 35))) val differentTypes = track(9.tracked[String].toString) assert(differentTypes == ("9", Set(9))) } 

track performs the function of tracking tracked calls in Int instances (for example, 7.tracked ).

Is it possible to point the type parameter to tracked implicit, so the following compiles:

 track(7.tracked + 35.tracked) 
+8
scala type-inference continuations
source share
2 answers

Your question made me think about how a sequel can track a condition. So I adapted this to your case and came up with the following:

 import util.continuations._ object TrackingTest extends App { type State = Set[Int] type ST = State => State implicit class Tracked(val i: Int) extends AnyVal { def tracked = shift{ (k: Int=>ST) => (state:State) => k(i)(state + i) } } def track[A](thunk: => A@cps[ST]): (A, State) = { var result: A = null.asInstanceOf[A] val finalSate = (reset { result = thunk (state:State) => state }).apply(Set[Int]()) (result, finalSate) } val result = track(7.tracked + 35.tracked) assert(result == (42, Set(7, 35))) val differentTypes = track(9.tracked.toString) assert(differentTypes == ("9", Set(9))) } 

This uses 2.10.1, but it works fine with 2.9.1, and also when replacing the implicit class with a value of 2.10.x:

 implicit def tracked(i: Int) = new { def tracked = shift{ (k: Int=>ST) => (state:State) => k(i)(state + i) } } 

The key change I made is to tracked not to use any type inference by fixing Int@cps[ST] . The CPS plugin then matches the calculation to the correct type (for example, String@cps[ST] ) as necessary. The state is locked by continuation, returning the State=>State function, which takes the current state (set of int values) and returns the next state. The reset type reset is a function from state to state (of type ST ), which will take the initial state and return the final state.

The final trick is to use var to capture the result, keeping the expected type to reset .

+2
source share

Although the exact answer to this question can only be asked by the authors of the compiler, we can guess that this is not possible by looking at the source code of the continuation plugin.

If you look at the source of the continuations, you can see this:

  val anfPhase = new SelectiveANFTransform() { val global = SelectiveCPSPlugin.this.global val runsAfter = List("pickler") } val cpsPhase = new SelectiveCPSTransform() { val global = SelectiveCPSPlugin.this.global val runsAfter = List("selectiveanf") } 

The anfPhase phase is executed after the pickler phase and cpsPhase after selectiveAnf. If you look at SelectiveANFTransform.scala

 abstract class SelectiveANFTransform extends PluginComponent with Transform with TypingTransformers with CPSUtils { // inherits abstract value `global' and class `Phase' from Transform import global._ // the global environment import definitions._ // standard classes and methods import typer.atOwner // methods to type trees /** the following two members override abstract members in Transform */ val phaseName: String = "selectiveanf" 

If we use phases of scalac -Xshow, we can see the phases during the compilation process:

 parser namer packageobjects typer superaccessors pickler refchecks selectiveanf liftcode selectivecps uncurry ...... 

As you can see, the typer phase is applied before the selectiveAnf and selectiveCps stages. It should be confirmed that type inference occurs in the typer phase, but if that is true and would be reasonable, it should now be clear why you cannot omit the Int type to 7.tracked and 35.tracked.

Now, if you are not satisfied yet, you should know that the compiler works by performing a set of transformations on the "trees", which you can see using the following parameters:

  • -Xprint: shows your scala code after a certain phase
  • -Xprint: -Show-trees show your scala code and trees after the phase is complete.
  • -YBrowse: opens a graphical interface for viewing both.
+1
source share

All Articles