Skip to content

Instantly share code, notes, and snippets.

@afsalthaj
Last active November 7, 2020 13:22
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 afsalthaj/9d9b3f79de5638c88c6cd53a2242a1b8 to your computer and use it in GitHub Desktop.
Save afsalthaj/9d9b3f79de5638c88c6cd53a2242a1b8 to your computer and use it in GitHub Desktop.
import cats.data.StateT
import cats.effect.{ IO, Resource }
import cats.syntax.traverse._
import cats.instances.list._
import Resources.StateInfo
final case class Resources[A](resources: List[Resource[IO, A]]) {
def executeAll: Resource[IO, List[A]] =
resources.sequence[Resource[IO, *], A]
/**
* @param f: Given a list of B (derived from A) already processed, and the current file A, execute the process to derive C.
* Resources are closed as an when they are used, unlike `execute`. Example: `Resources.trackDuplicate`
*/
def use[B, C](f: (List[B], A) => IO[C])(g: A => B): IO[List[C]] =
resources
.traverse[StateInfo[B, *], C](resource => {
for {
existingFiles <- StateT.get[IO, List[B]]
dataB <- StateT.liftF(resource.use(data => f(existingFiles, data).map(b => (data, b))))
_ <- StateT.set[IO, List[B]](g(dataB._1) :: existingFiles)
} yield dataB._2
})
.run(Nil: List[B])
.map(_._2)
}
object Resources {
type StateInfo[A, B] = StateT[IO, List[A], B]
def trackDuplicate[A, B, C](
f: A => IO[C]
)(g: A => B)(onDuplicate: B => String): (List[B], A) => IO[C] = { (state, resource) =>
if (state.contains(g(resource))) {
IO.raiseError(new RuntimeException(onDuplicate(g(resource))))
} else f(resource)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment