get
call arrives before the variable can be populated
sealed trait State[A]
case class FirstCall(wait: Deferred[F, A]) extends State[A]
case class NextCalls(v: A) extends State[A]
create
method of the abstraction (I'll show you that in a bit), so that's why there is no F[_]
parameter, it's normally in the outer definition
Ref[F, State[A]]
as your main component
@ChristopherDavenport do you mean
, so that's why there is no F[_] parameter, it's normally in the outer definition
trait Thing[F[_], A] {
def get: F[A]
}
object Thing {
def create[F[_]: Concurrent: Timer, A](
action: F[A],
t: FiniteDuration
): Resource[F, Thing[F, A]] = {
sealed trait State
case class FirstCall(waitV: Deferred[F, A]) extends State
case class NextCalls(v: A) extends State
val initial = for {
d <- Deferred[F, A]
r <- Ref[F].of(FirstCall(d): State)
} yield r
Stream
.eval(initial)
.flatMap { state =>
val read = new Thing[F, A] {
def get = state.get.flatMap {
case FirstCall(wait) => wait.get
case NextCalls(v) => v.pure[F]
}
}
val write = action.flatMap { v =>
state.modify {
case FirstCall(wait) => NextCalls(v) -> wait.complete(v).void
case NextCalls(_) => NextCalls(v) -> ().pure[F]
}.flatten
}
Stream.emit(read).concurrently(Stream.repeatEval(write).metered(t))
}
.compile
.resource
.lastOrError
}
}
something along these lines
cats
instead.
unattempt