Last active
August 11, 2023 09:46
-
-
Save nzpr/bf46db2b14c65a5c006edbd2f5704db0 to your computer and use it in GitHub Desktop.
Eval in PrN
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import scala.annotation.tailrec | |
import cats.Eval | |
import cats.syntax.all._ | |
/** Testing lazy evaluation of connectiveUsed for ParMetaData. */ | |
final class ParMetaData(val connectiveUsed: Eval[Boolean]) | |
/** Par with metadata. */ | |
sealed trait Par { | |
protected def meta: ParMetaData | |
val connectiveUsed: Eval[Boolean] = meta.connectiveUsed | |
} | |
/** Expression par. */ | |
sealed trait Expr extends Par | |
/** Compute connectiveUsed for seq of Pars. */ | |
def connectiveUsedParProc(ps: Seq[Par]): Eval[Boolean] = { | |
// fold monadic to ensure stack safety | |
ps.foldM[Eval, Boolean](false){ case (acc,x) => | |
x.connectiveUsed.map { x => | |
println("Computing.") | |
x || acc | |
} | |
} // memoize result | |
.memoize | |
} | |
/** Par process which is seq of Pars. */ | |
case class ParProc(ps: Seq[Par], protected val meta: ParMetaData) extends Par {} | |
object ParProc { | |
def apply(ps: Seq[Par]): ParProc = { | |
val meta = new ParMetaData(connectiveUsedParProc(ps)) | |
new ParProc(ps, meta) | |
} | |
} | |
/** Ground type of Int. */ | |
final case class GInt(v: Long, protected val meta: ParMetaData) extends Expr | |
object GInt { | |
private def connectiveUsedGInt(v: Long): Boolean = false | |
def apply(v: Long): GInt = { | |
val meta = new ParMetaData(Eval.later(connectiveUsedGInt(v))) | |
new GInt(v, meta) | |
} | |
} | |
/** Make nested Par of a particular depth. */ | |
@tailrec | |
def hugePar(n: Int, par: Par = GInt(0)): Par = | |
if (n == 0) par | |
else hugePar(n - 1, ParProc(Seq(par))) | |
/** Print all values for the whole nested tree. */ | |
def printNestedValues(par: Par): Unit = { | |
par match { | |
case g@ GInt(_,_) => println(g.connectiveUsed.value) | |
case _@ ParProc(g,_) => | |
g.foreach(x => println(x.connectiveUsed.value)) | |
println(g) | |
printNestedValues(g.head) | |
case _ => ??? | |
} | |
} | |
// Create huge nested par | |
val par = hugePar(5) | |
println("-> Instantiating huge par. No computation should be done yet.") | |
println(par.connectiveUsed) | |
println("-> Rendering value. Computation should be evaluated now.") | |
println(par.connectiveUsed.value) | |
println("-> Rendering values for nested Par. Should be cached and not reevaluated.") | |
printNestedValues(par) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import scala.annotation.tailrec | |
import cats.Eval | |
import cats.syntax.all._ | |
/** Testing lazy evaluation of connectiveUsed for ParMetaData. */ | |
final class ParMetaData(val connectiveUsed: Eval[Boolean]) | |
/** Par with metadata. */ | |
sealed trait Par { | |
protected def meta: ParMetaData | |
val connectiveUsed: Eval[Boolean] = meta.connectiveUsed.memoize | |
} | |
/** Expression par. */ | |
sealed trait Expr extends Par | |
/** Compute connectiveUsed for seq of Pars. */ | |
def connectiveUsedParProc(ps: Seq[Par]): Eval[Boolean] = { | |
// fold monadic to ensure stack safety | |
ps.foldM[Eval, Boolean](false){ case (acc,x) => | |
x.connectiveUsed.map { x => | |
println("Computing.") | |
x || acc | |
} | |
} | |
} | |
/** Par process which is seq of Pars. */ | |
class ParProc(val ps: Seq[Par], protected val meta: ParMetaData) extends Par {} | |
object ParProc { | |
def apply(ps: Seq[Par]): ParProc = { | |
val meta = new ParMetaData(connectiveUsedParProc(ps)) | |
new ParProc(ps, meta) | |
} | |
} | |
/** Ground type of Int. */ | |
final class GInt(val v: Long, protected val meta: ParMetaData) extends Expr | |
object GInt { | |
private def connectiveUsedGInt(v: Long): Eval[Boolean] = | |
Eval.later { | |
println("Troll") | |
false | |
} | |
def apply(v: Long): GInt = { | |
val meta = new ParMetaData(connectiveUsedGInt(v)) | |
new GInt(v, meta) | |
} | |
} | |
/** Make nested Par of a particular depth. */ | |
@tailrec | |
def hugePar(n: Int, par: Par = GInt(0)): Par = | |
if (n == 0) par | |
else hugePar(n - 1, ParProc(Seq(par))) | |
// Create huge nested par | |
val depth = 100000 | |
// Print all values in nested structure | |
def traverse(par: Par) = LazyList.unfold(par.asInstanceOf[ParProc]){x => | |
x.ps.headOption.map{y => (y.connectiveUsed.value, y.asInstanceOf[ParProc])} | |
} | |
println("-> Instantiating huge par. No computation should be done yet.") | |
val par = hugePar(depth) | |
println(par.connectiveUsed) | |
println("-> Rendering value. Computation should be evaluated now.") | |
println(par.connectiveUsed.value) | |
println("-> Printing value again") | |
println(par.connectiveUsed.value) | |
println("-> Rendering value of all nested objects. Should be cached and not reevaluated.") | |
// -1 because the last iteration will crash on .asInstanceOf[ParProc] | |
println(traverse(par).map(println).take(depth-1).last) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import scala.annotation.tailrec | |
import cats.Eval | |
import cats.syntax.all._ | |
/** Testing lazy evaluation of connectiveUsed for ParMetaData. */ | |
final class ParMetaData(val connectiveUsed: Eval[Int]) | |
/** Par with metadata. */ | |
sealed trait Par { | |
protected def meta: ParMetaData | |
val connectiveUsed: Eval[Int] = meta.connectiveUsed.memoize | |
} | |
/** Expression par. */ | |
sealed trait Expr extends Par | |
/** Compute connectiveUsed for seq of Pars. */ | |
def connectiveUsedParProc(ps: Seq[Par]): Eval[Int] = { | |
ps.head.connectiveUsed.map(_+1) | |
} | |
/** Par process which is seq of Pars. */ | |
class ParProc(val ps: Seq[Par], protected val meta: ParMetaData) extends Par {} | |
object ParProc { | |
def apply(ps: Seq[Par]): ParProc = { | |
val meta = new ParMetaData(connectiveUsedParProc(ps)) | |
new ParProc(ps, meta) | |
} | |
} | |
/** Ground type of Int. */ | |
final class GInt(val v: Long, protected val meta: ParMetaData) extends Expr | |
object GInt { | |
private def connectiveUsedGInt(v: Long): Eval[Int] = | |
Eval.later { | |
println("Troll") | |
0 | |
} | |
def apply(v: Long): GInt = { | |
val meta = new ParMetaData(connectiveUsedGInt(v)) | |
new GInt(v, meta) | |
} | |
} | |
/** Make nested Par of a particular depth. */ | |
@tailrec | |
def hugePar(n: Int, par: Par = GInt(0)): Par = | |
if (n == 0) par | |
else hugePar(n - 1, ParProc(Seq(par))) | |
// Create huge nested par | |
val depth = 100000 | |
// Print all values in nested structure | |
def traverse(par: Par) = LazyList.unfold(par.asInstanceOf[ParProc]){x => | |
x.ps.headOption.map{y => (y.connectiveUsed.value, y.asInstanceOf[ParProc])} | |
} | |
println("-> Instantiating huge par. No computation should be done yet.") | |
val par = hugePar(depth) | |
println(par.connectiveUsed) | |
println("-> Rendering value. Computation should be evaluated now.") | |
println(par.connectiveUsed.value) | |
println("-> Printing value again") | |
println(par.connectiveUsed.value) | |
println("-> Rendering value of all nested objects. Should be cached and not reevaluated.") | |
// -1 because the last iteration will crash on .asInstanceOf[ParProc] | |
println(traverse(par).map(println).take(depth-1).last) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment