Search code examples
scalacontinuations

Does "reset" require "shift" inside the block?


Is it correct that reset requires shift inside the block? I tried it and got the following:

scala> reset {} 
error: cannot cps-transform expression (): type arguments [Unit,Unit,Nothing]
do not conform to method shiftUnit's type parameter bounds [A,B,C >: B]

It looks reasonable (since reset block without shift inside is "dead code", which is never executed) but I do not understand the error.

What is the exact meaning of the error message?


Solution

  • I don't agree, that code within reset is dead without shift. Actually reset just defines the boundaries of a continuation (that's because they are called delimited continuations).The code would be dead if you have shift somewhere within reset and you do not call continuation function. For example:

    reset {
      println(1)
      shift((k: Unit => Unit) => println(2))
      println(3)
    }
    

    The code after shift is dead (println(3)) because I have not called k(Unit).

    From the other hand, seems that reset expects some special return type from it's body - the one that annotated with @cpsParam annotation. You can check definition of reset method:

    def reset[A,C](ctx: => (A @cpsParam[A,C])): C = ...
    

    And shift produces just what reset method expects. Here is definition of shift method:

    def shift[A,B,C](fun: (A => B) => C): A @cpsParam[B,C] = ...
    

    But you still can use reset without shift call within it. This trick will do it:

    def foo[T](body: => T @cps[Any]) = reset(body)
    
    foo {
      println("it works")
    }
    

    Please note, that @cps is just type alias for @cpsParam. Here it's definition:

    type cps[A] = cpsParam[A, A]