Skip to content

Instantly share code, notes, and snippets.

@nzpr
Last active August 11, 2023 09:46
Show Gist options
  • Save nzpr/bf46db2b14c65a5c006edbd2f5704db0 to your computer and use it in GitHub Desktop.
Save nzpr/bf46db2b14c65a5c006edbd2f5704db0 to your computer and use it in GitHub Desktop.
Eval in PrN
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)
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)
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