Skip to content

Instantly share code, notes, and snippets.

@t3hnar
Created January 9, 2019 16:37
Show Gist options
  • Save t3hnar/0d2d0ba825a70bf0584a4d3cd25c0efe to your computer and use it in GitHub Desktop.
Save t3hnar/0d2d0ba825a70bf0584a4d3cd25c0efe to your computer and use it in GitHub Desktop.
SerialRef.scala
import cats.effect._
import cats.effect.concurrent.{Ref, Semaphore}
import cats.implicits._
trait SerialRef[F[_], A] {
def get: F[A]
def modify[B](f: A => F[(A, B)]): F[B]
def update(f: A => F[A]): F[Unit]
}
object SerialRef {
def of[F[_] : Concurrent, A](value: A): F[SerialRef[F, A]] = {
for {
s <- Semaphore[F](1)
r <- Ref[F].of(value)
} yield {
new SerialRef[F, A] {
def get = r.get
def modify[B](f: A => F[(A, B)]) = {
s.withPermit {
for {
a <- r.get
ab <- f(a)
(a, b) = ab
_ <- r.set(a)
} yield b
}
}
def update(f: A => F[A]) = {
modify { a =>
for {
a <- f(a)
} yield {
(a, ())
}
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment