Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import cats.syntax.all._
- import cats.effect.IO
- sealed trait Memo[A] {
- def get: IO[A]
- }
- object Memo {
- def make[A](a: => IO[A]): Memo[A] = new Memo[A] {
- @volatile var cache: Option[A] = None
- def get: IO[A] = IO {
- cache match {
- case None =>
- a.flatMap { r =>
- IO { cache = Some(r); r }
- }
- case Some(x) =>
- IO.pure(x)
- }
- }.flatten
- }
- }
- val impure: IO[Int] = IO { println("impure"); 10 }
- val a = Memo.make(impure)
- (a.get *> a.get).unsafeRunSync // prints once
- // inline
- (Memo.make(impure).get *> Memo.make(impure).get).unsafeRunSync // prints twice
- (for {
- r <- IORef.make[Int](0)
- impure = for {
- v <- r.get
- _ <- r.set(v + 1)
- } yield ()
- a = Memo.make(impure)
- _ <- a.get *> a.get
- v <- r.get
- _ <- IO { println(v) }
- } yield ()).unsafeRunSync // prints 1
- (for {
- r <- IORef.make[Int](0)
- impure = for {
- v <- r.get
- _ <- r.set(v + 1)
- } yield ()
- // all I did was inline a
- _ <- Memo.make(impure).get *> Memo.make(impure).get
- v <- r.get
- _ <- IO { println(v) }
- } yield ()).unsafeRunSync // prints 2
- /////////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////////
- sealed trait IORef[A] {
- def get: IO[A]
- def set(a: A): IO[Unit]
- }
- object IORef {
- def make[A](a: A): IO[IORef[A]] = IO {
- new IORef[A] {
- var value: A = a
- def get: IO[A] = IO { value }
- def set(a: A): IO[Unit] = IO { value = a }
- }
- }
- }
Add Comment
Please, Sign In to add comment