Skip to content

Instantly share code, notes, and snippets.

@deusaquilus
Last active March 12, 2021 06:42
Show Gist options
  • Save deusaquilus/03428d7dd03c7a6815d5b49e0f2b6a59 to your computer and use it in GitHub Desktop.
Save deusaquilus/03428d7dd03c7a6815d5b49e0f2b6a59 to your computer and use it in GitHub Desktop.
Various Zio Bracketing Functions: TODO Check if these work in Dotty
// Provide a single Environment Has clause:
// ZLayer[Orig, E, Has[From] with Rest] => ZLayer[Orig, E, Has[To] with Rest]
def projectionWithEffect[From: Tag, To: Tag, Rest <: Has[_]: Tag, E](effect: (From, Rest) => IO[E, To]): ZLayer[Has[From] with Rest, E, Has[To] with Rest] =
(for {
from <- ZIO.service[From]
rest <- ZIO.environment[Rest]
result <- effect(from, rest)
} yield Has(result) ++ rest).toLayerMany
def projectWithEffectBracket[Orig: Tag, From: Tag, To: Tag, Rest <: Has[_]: Tag, E](effect: (From, Rest) => IO[E, To])(layer: ZLayer[Orig, E, Has[From] with Rest]): ZLayer[Orig, E, Has[To] with Rest] =
layer >>> projectionWithEffect[From, To, Rest, E](effect)
// Provide a single Environment Has clause with a bracketing effect:
// ZLayer[Orig, E, Has[From] with Rest] (and close To afterward) => ZLayer[Orig, E, Has[To] with Rest]
def projectionWithManagedEffectBracket1[From: Tag, To: Tag, Rest <: Has[_]: Tag, E](managed: (Has[From] with Rest) => Managed[E, To]): ZLayer[Has[From] with Rest, E, Has[To] with Rest] =
(for {
fromEnv <- ZManaged.environment[Has[From]]
restEnv <- ZManaged.environment[Rest]
from = fromEnv.get[From]
result <- managed(fromEnv ++ restEnv)
} yield Has(result) ++ restEnv).toLayerMany
def projectionWithManagedEffectBracket2[From: Tag, To: Tag, Rest <: Has[_]: Tag, E](managed: (Has[From], Rest) => Managed[E, To]): ZLayer[Has[From] with Rest, E, Has[To] with Rest] =
(for {
fromEnv <- ZManaged.environment[Has[From]]
restEnv <- ZManaged.environment[Rest]
from = fromEnv.get[From]
result <- managed(fromEnv, restEnv)
} yield Has(result) ++ restEnv).toLayerMany
// It would be really nice to be able to wrap the dependencies in a ZManaged that is passed in however...
// it won't work either because Scala can't figure out what 'Rest' is
def projectionWithManagedEffectBracket1[From: Tag, To: Tag, Rest <: Has[_]: Tag, E](managed: ZManaged[Has[From] with Rest, E, To]): ZLayer[Has[From] with Rest, E, Has[To] with Rest] =
(for {
fromEnv <- ZManaged.environment[Has[From]]
restEnv <- ZManaged.environment[Rest]
from = fromEnv.get[From]
result <- managed.provide(fromEnv ++ restEnv)
} yield Has(result) ++ restEnv).toLayerMany
// This won't work either because Scala can't figure out what 'Rest' is
def projectionWithManagedEffectBracket1[From: Tag, To: Tag, Rest <: Has[_]: Tag, E](managed: (Has[From] with Rest) => Managed[E, To]): ZLayer[Has[From] with Rest, E, Has[To] with Rest] =
(for {
fromEnv <- ZManaged.environment[Has[From]]
restEnv <- ZManaged.environment[Rest]
from = fromEnv.get[From]
result <- managed(fromEnv ++ restEnv)
} yield Has(result) ++ restEnv).toLayerMany
// Mapping Auto-Closeable Layers
def mapAutoCloseableGeneric[From: Tag, To <: AutoCloseable: Tag](mapping: From => To): ZLayer[Has[From] with Blocking, Throwable, Has[To] with Blocking] = {
val managed =
for {
fromBlocking <- ZManaged.environment[Has[From] with Blocking]
from = fromBlocking.get[From]
blocking = fromBlocking.get[Blocking.Service]
r <- ZManaged.fromAutoCloseable(Task(mapping(from)))
} yield Has(r) ++ Has(blocking)
ZLayer.fromManagedMany(managed)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment