Skip to content

Instantly share code, notes, and snippets.

@gvolpe
Last active April 20, 2020 17:49
Show Gist options
  • Save gvolpe/4d12f0ffbc16cebbb5163152d8769dfb to your computer and use it in GitHub Desktop.
Save gvolpe/4d12f0ffbc16cebbb5163152d8769dfb to your computer and use it in GitHub Desktop.
collectSuccessful :: [IO a] -> IO [a]
collectSuccessful xs = do
ref <- newIORef []
parTraverse (f ref) xs `onError` readIORef ref
where
f ref fa = fromEitherIO $ try fa >>= \a -> action ref a $> a
action ref a = case a of
(Right x) -> void $ atomicModifyIORef ref (\y -> (x : y, x))
(Left _) -> pure ()
def generic[F[_]: MonadError[?[_], Throwable], G[_]: Traverse, A](
gfa: G[F[A]],
append: G[A] => A => G[A],
ref: Ref[F, G[A]]
): F[G[A]] =
gfa.traverse(_.attempt.flatTap {
case Right(x) => ref.update(append(_)(x))
case Left(_) => Applicative[F].unit
}.rethrow)
.handleErrorWith(_ => ref.get)
generic[IOIO, , ListList, , StringString](list2, g => x => g :+ x, ref)](list2, g => x => g :+ x, ref)
val ioa = IO.sleep(1.second) *> IO.pure("a")
val iob = IO.pure("b")
val ioc = IO.pure("c")
val iod = IO.sleep(3.seconds) *> IO.pure("d")
val ioe = IO.sleep(2.seconds) *> IO.pure("e")
val list1 = List(ioa, iob, ioc, iod, ioe)
val list2 = List(ioa, iob, IO.raiseError(new Exception("boom")), iod, ioe)
def collectSuccessful(list: List[IO[String]])(ref: Ref[IO, List[String]]): IO[List[String]] =
list
.traverse(_.attempt.flatTap {
case Right(x) => ref.update(_ :+ x)
case Left(_) => IO.unit
}.rethrow)
.handleErrorWith(_ => ref.get)
val program = Ref.of[IO, List[String]](List.empty).flatMap { ref =>
collectSuccessful(list2)(ref).flatMap(x => IO(println(x)))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment