F代数的状态实现
Stateful implementation of F-algebra
考虑以下简单的 F 代数
trait Test[F[_]] {
def add(i: Int): F[Unit]
}
我想提供它的实现来跟踪所有添加的值并添加那些尚未添加的值。它必须以线程安全的方式完成。
我能想到的“最佳”实现是使用 MVar[F, Ref[F, List[Int]]]
。这是它的样子
def statefulMutexTest[F[_]: Concurrent] = {
val mvarRef: F[MVar[F, Ref[F, List[Int]]]] =
for {
ref <- Ref.of[F, List[Int]](List.empty[Int])
mvar <- MVar.of[F, Ref[F, List[Int]]](ref)
} yield mvar
mvarRef map { mvar =>
new Test[F] {
override def add(i: Int): F[Unit] =
mvar.take.bracket(ref =>
for {
list <- ref.get
_ <- if (!list.contains(i)) ref.set(list :+ i) else Applicative[F].unit
} yield ())(mvar.put)
}
}
}
它看起来很乱,但按预期工作。我最初想到使用 StateT
,但我不喜欢将状态导出到客户端的想法。
基本上 Ref
是我通常在这种情况下使用的所有内容,Test
这里只是一个特定于域的包装器:
object Test {
def of[F[_]: Sync]: F[Test[F]] =
Ref.of[F, Set[Int]](Set.empty).map(ref => (i: Int) => ref.update(_ + i).void)
}
考虑以下简单的 F 代数
trait Test[F[_]] {
def add(i: Int): F[Unit]
}
我想提供它的实现来跟踪所有添加的值并添加那些尚未添加的值。它必须以线程安全的方式完成。
我能想到的“最佳”实现是使用 MVar[F, Ref[F, List[Int]]]
。这是它的样子
def statefulMutexTest[F[_]: Concurrent] = {
val mvarRef: F[MVar[F, Ref[F, List[Int]]]] =
for {
ref <- Ref.of[F, List[Int]](List.empty[Int])
mvar <- MVar.of[F, Ref[F, List[Int]]](ref)
} yield mvar
mvarRef map { mvar =>
new Test[F] {
override def add(i: Int): F[Unit] =
mvar.take.bracket(ref =>
for {
list <- ref.get
_ <- if (!list.contains(i)) ref.set(list :+ i) else Applicative[F].unit
} yield ())(mvar.put)
}
}
}
它看起来很乱,但按预期工作。我最初想到使用 StateT
,但我不喜欢将状态导出到客户端的想法。
基本上 Ref
是我通常在这种情况下使用的所有内容,Test
这里只是一个特定于域的包装器:
object Test {
def of[F[_]: Sync]: F[Test[F]] =
Ref.of[F, Set[Int]](Set.empty).map(ref => (i: Int) => ref.update(_ + i).void)
}