scala - Continuations and for comprehensions -- what's the incompatibility? -
scala - Continuations and for comprehensions -- what's the incompatibility? -
i new scala , trying wrap head around continuations i'm trying reproduce yield return
c# statement.
following this post, have written next code :
package com.company.scalatest import scala.util.continuations._; object gentest { val gen = new generator[int] { def produce = { yieldvalue(1) yieldvalue(2) yieldvalue(3) yieldvalue(42) } } // not compile :( // val gen2 = new generator[int] { // def produce = { // var ints = list(1, 2, 3, 42); // // ints.foreach((theint) => yieldvalue(theint)); // } // } // works? val gen3 = new generator[int] { def produce = { var ints = list(1, 2, 3, 42); var = 0; while (i < ints.length) { yieldvalue(ints(i)); = + 1; } } } def main(args: array[string]): unit = { gen.foreach(println); // gen2.foreach(println); gen3.foreach(println); } } abstract class generator[e] { var loopfn: (e => unit) = null def produce(): unit @cps[unit] def foreach(f: => (e => unit)): unit = { loopfn = f reset[unit, unit](produce) } def yieldvalue(value: e) = shift { genk: (unit => unit) => loopfn(value) genk(()) () } }
as can see, gen2
commented out not compile. since can iterate on content of list using while loop (see gen3
), expected foreach loop work well.
the compilation error next :
no type parameters method foreach: (f: int => b)unit exist can applied arguments (int => unit @scala.util.continuations.cpsparam[unit,unit]) --- because --- argument expression's type not compatible formal parameter type; found : int => unit @scala.util.continuations.cpsparam[unit,unit] required: int => ?b
why error , there way work around cleaner while loop?
thank you
first let's @ take gen2
compile.
object cpsconversions { import scala.collection.iterablelike import scala.util.continuations._ implicit def cpsiterable[a, repr](xs: iterablelike[a, repr]) = new { def cps = new { def foreach[b](f: => any@cpsparam[unit, unit]): unit@cpsparam[unit, unit] = { val = xs.iterator while(it.hasnext) f(it.next) } } } } object gentest { import cpsconversions.cpsiterable val gen2 = new generator[int] { def produce = { var ints = list(1, 2, 3, 42) ints.cps.foreach((theint) => yieldvalue(theint)) } }
now let's take @ what's going on. original gen2
fails compile on next line:
ints.foreach((theint) => yieldvalue(theint))
since type of yieldvalue
includes @cpsparam
annotation, continuations plugin transforms function passed foreach
method 1 of type:
int => unit @cpsparam[unit,unit]
way in hierarchy of list[int]
, you'll see foreach
defined as:
foreach [u] (f: (int) ⇒ u): unit
this problem, types not match , scala doesn't know how int => u
int => unit @cpsparam[unit,unit]
. prepare it, added cps version of foreach
in implicit conversion, can access calling cps
on iterablelike
.
it nice if implicit conversion done without explicit cps
call, have not found way create scala compiler recognize applicability of such implicit conversion pimp new foreach
onto list. might have order in compiler uses continuations plugin, know far little process sure.
so that's , foreach
. question mentions comprehensions, require of filter
, map
, or flatmap
defined (depending on goes on in comprehension). have implemented these in link in above comment, extends cpsconversions
object above allow general comprehensions.
scala generator yield continuations continuation-passing
Comments
Post a Comment