Skip to content

Instantly share code, notes, and snippets.

@filosganga
Last active March 5, 2020 20:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save filosganga/cbb1d46da1d1eabc86cf93c8cfcdb351 to your computer and use it in GitHub Desktop.
Save filosganga/cbb1d46da1d1eabc86cf93c8cfcdb351 to your computer and use it in GitHub Desktop.
Computational memoization
import cats._
import cats.implicits._
import cats.effect._
import cats.effect.concurrent._
import cats.effect.implicits._
trait Memoize[F[_], Key, A] {
def get(id: Key): F[A]
}
object Memoize {
def apply[F[_]: Concurrent, Key, A](f: Key => F[A]): F[Memoize[F, Key, A]] =
Ref[F].of(Map.empty[Key, Deferred[F, Either[Throwable, A]]]).map { state =>
new Memoize[F, Key, A] {
def get(id: Key): F[A] =
Deferred[F, Either[Throwable, A]].flatMap { deferred =>
state
.modify { hashMap =>
val completeDeferred = f(id).attempt
.flatTap(deferred.complete)
.uncancelable
hashMap.get(id) match {
case None => (hashMap + (id -> deferred), completeDeferred)
case Some(d) => (hashMap, d.get)
}
}
.flatten
.rethrow
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment