Skip to content

Commit

Permalink
BIO: remove all redundant variances on typeclass instance methods (#1052
Browse files Browse the repository at this point in the history
)
  • Loading branch information
neko-kai committed May 10, 2020
1 parent 4235bff commit 448c40d
Show file tree
Hide file tree
Showing 9 changed files with 163 additions and 101 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ trait BIOError3[F[-_, +_, +_]] extends BIOGuarantee3[F] with BIOBifunctor3[F] {
override val InnerF: BIOFunctor3[F] = this

def fail[E](v: => E): F[Any, E, Nothing]
def catchAll[R, E, A, E2, A2 >: A](r: F[R, E, A])(f: E => F[R, E2, A2]): F[R, E2, A2]
def catchSome[R, E, A, E2 >: E, A2 >: A](r: F[R, E, A])(f: PartialFunction[E, F[R, E2, A2]]): F[R, E2, A2]
def catchAll[R, E, A, E2](r: F[R, E, A])(f: E => F[R, E2, A]): F[R, E2, A]
def catchSome[R, E, A, E1 >: E](r: F[R, E, A])(f: PartialFunction[E, F[R, E1, A]]): F[R, E1, A]

def fromEither[E, V](effect: => Either[E, V]): F[Any, E, V]
def fromOption[E, A](errorOnNone: => E)(effect: => Option[A]): F[Any, E, A]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
package izumi.functional.bio

trait BIOMonad3[F[-_, +_, +_]] extends BIOApplicative3[F] {
def flatMap[R, E, A, R2 <: R, E2 >: E, B](r: F[R, E, A])(f: A => F[R2, E2, B]): F[R2, E2, B]
def flatMap[R, E, A, B](r: F[R, E, A])(f: A => F[R, E, B]): F[R, E, B]
def flatten[R, E, A](r: F[R, E, F[R, E, A]]): F[R, E, A] = flatMap(r)(identity)

def tailRecM[R, E, A, B](a: A)(f: A => F[R, E, Either[A, B]]): F[R, E, B] =
flatMap(f(a)) {
case Left(next) => tailRecM(next)(f)
case Right(res) => pure(res)
}

def tap[R, E, A, R2 <: R, E2 >: E](r: F[R, E, A])(f: A => F[R2, E2, Unit]): F[R2, E2, A] = flatMap[R, E, A, R2, E2, A](r)(a => as(f(a))(a))
def tap[R, E, A](r: F[R, E, A])(f: A => F[R, E, Unit]): F[R, E, A] = flatMap(r)(a => as(f(a))(a))
@inline final def when[R, E, E1](cond: F[R, E, Boolean])(ifTrue: F[R, E1, Unit])(implicit ev: E <:< E1): F[R, E1, Unit] = {
ifThenElse(cond)(ifTrue, unit)
}
@inline final def unless[R, E, E1](cond: F[R, E, Boolean])(ifFalse: F[R, E1, Unit])(implicit ev: E <:< E1): F[R, E1, Unit] = {
ifThenElse(cond)(unit, ifFalse)
}
@inline final def ifThenElse[R, E, E1, A](cond: F[R, E, Boolean])(ifTrue: F[R, E1, A], ifFalse: F[R, E1, A])(implicit @deprecated("unused","") ev: E <:< E1): F[R, E1, A] = {
@inline final def ifThenElse[R, E, E1, A](
cond: F[R, E, Boolean]
)(ifTrue: F[R, E1, A],
ifFalse: F[R, E1, A],
)(implicit @deprecated("unused", "") ev: E <:< E1
): F[R, E1, A] = {
flatMap(cond.asInstanceOf[F[R, E1, Boolean]])(if (_) ifTrue else ifFalse)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ trait BIOMonadError3[F[-_, +_, +_]] extends BIOError3[F] with BIOMonad3[F] {
def leftFlatMap[R, E, A, E2](r: F[R, E, A])(f: E => F[R, Nothing, E2]): F[R, E2, A] = {
redeem(r)(e => flatMap(f(e))(fail(_)), pure)
}
def tapBoth[R, E, A, E2 >: E](r: F[R, E, A])(err: E => F[R, E2, Unit], succ: A => F[R, E2, Unit]): F[R, E2, A] = {
tap(tapError[R, E, A, E2](r)(err))(succ)
def tapBoth[R, E, A, E1 >: E](r: F[R, E, A])(err: E => F[R, E1, Unit], succ: A => F[R, E1, Unit]): F[R, E1, A] = {
tap(tapError[R, E, A, E1](r)(err))(succ)
}
/** for-comprehensions sugar:
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import scala.concurrent.duration.{Duration, FiniteDuration}
trait BIOTemporal3[F[-_, +_, +_]] extends BIOAsync3[F] with BIOTemporalInstances {
def sleep(duration: Duration): F[Any, Nothing, Unit]
def timeout[R, E, A](r: F[R, E, A])(duration: Duration): F[R, E, Option[A]]
def retryOrElse[R, A, E, A2 >: A, E2](r: F[R, E, A])(duration: FiniteDuration, orElse: => F[R, E2, A2]): F[R, E2, A2]
def retryOrElse[R, E, A, E2](r: F[R, E, A])(duration: FiniteDuration, orElse: => F[R, E2, A]): F[R, E2, A]

@inline final def repeatUntil[R, E, A](action: F[R, E, Option[A]])(onTimeout: => E, sleep: FiniteDuration, maxAttempts: Int): F[R, E, A] = {
def go(n: Int): F[R, E, A] = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,17 @@ class BIOAsyncZio extends BIOAsync3[ZIO] with BIOLocal[ZIO] {
@inline override final def flip[R, E, A](r: ZIO[R, E, A]): ZIO[R, A, E] = r.flip
@inline override final def bimap[R, E, A, E2, B](r: ZIO[R, E, A])(f: E => E2, g: A => B): ZIO[R, E2, B] = r.bimap(f, g)

@inline override final def flatMap[R, E, A, R1 <: R, E1 >: E, B](r: ZIO[R, E, A])(f0: A => ZIO[R1, E1, B]): ZIO[R1, E1, B] = r.flatMap(f0)
@inline override final def tap[R, E, A, R1 <: R, E2 >: E](r: ZIO[R, E, A])(f: A => ZIO[R1, E2, Unit]): ZIO[R1, E2, A] = r.tap(f)
@inline override final def tapBoth[R, E, A, E2 >: E](r: ZIO[R, E, A])(err: E => ZIO[R, E2, Unit], succ: A => ZIO[R, E2, Unit]): ZIO[R, E2, A] = r.tapBoth(err, succ)
@inline override final def flatMap[R, E, A, B](r: ZIO[R, E, A])(f0: A => ZIO[R, E, B]): ZIO[R, E, B] = r.flatMap(f0)
@inline override final def tap[R, E, A](r: ZIO[R, E, A])(f: A => ZIO[R, E, Unit]): ZIO[R, E, A] = r.tap(f)
@inline override final def tapBoth[R, E, A, E1 >: E](r: ZIO[R, E, A])(err: E => ZIO[R, E1, Unit], succ: A => ZIO[R, E1, Unit]): ZIO[R, E1, A] = r.tapBoth(err, succ)
@inline override final def flatten[R, E, A](r: ZIO[R, E, ZIO[R, E, A]]): ZIO[R, E, A] = ZIO.flatten(r)
@inline override final def *>[R, E, A, B](f: ZIO[R, E, A], next: => ZIO[R, E, B]): ZIO[R, E, B] = f *> next
@inline override final def <*[R, E, A, B](f: ZIO[R, E, A], next: => ZIO[R, E, B]): ZIO[R, E, A] = f <* next
@inline override final def <*[R, E, A, B](f: ZIO[R, E, A], next: => ZIO[R, E, B]): ZIO[R, E, A] = f <* next
@inline override final def map2[R, E, A, B, C](r1: ZIO[R, E, A], r2: => ZIO[R, E, B])(f: (A, B) => C): ZIO[R, E, C] = r1.zipWith(r2)(f)

@inline override final def redeem[R, E, A, E2, B](r: ZIO[R, E, A])(err: E => ZIO[R, E2, B], succ: A => ZIO[R, E2, B]): ZIO[R, E2, B] = r.foldM(err, succ)
@inline override final def catchAll[R, E, A, E2, A2 >: A](r: ZIO[R, E, A])(f: E => ZIO[R, E2, A2]): ZIO[R, E2, A2] = r.catchAll(f)
@inline override final def catchSome[R, E, A, E2 >: E, A2 >: A](r: ZIO[R, E, A])(f: PartialFunction[E, ZIO[R, E2, A2]]): ZIO[R, E2, A2] = r.catchSome(f)
@inline override final def catchAll[R, E, A, E2](r: ZIO[R, E, A])(f: E => ZIO[R, E2, A]): ZIO[R, E2, A] = r.catchAll(f)
@inline override final def catchSome[R, E, A, E1 >: E](r: ZIO[R, E, A])(f: PartialFunction[E, ZIO[R, E1, A]]): ZIO[R, E1, A] = r.catchSome(f)
@inline override final def withFilter[R, E, A](r: ZIO[R, E, A])(predicate: A => Boolean)(implicit ev: NoSuchElementException <:< E): ZIO[R, E, A] =
new ZIOWithFilterOps(r).withFilter(predicate)(ev)

Expand All @@ -57,7 +57,11 @@ class BIOAsyncZio extends BIOAsync3[ZIO] with BIOLocal[ZIO] {
@inline override final def bracket[R, E, A, B](acquire: ZIO[R, E, A])(release: A => ZIO[R, Nothing, Unit])(use: A => ZIO[R, E, B]): ZIO[R, E, B] = {
ZIO.bracket(acquire)(release)(use)
}
@inline override final def bracketCase[R, E, A, B](acquire: ZIO[R, E, A])(release: (A, BIOExit[E, B]) => ZIO[R, Nothing, Unit])(use: A => ZIO[R, E, B]): ZIO[R, E, B] = {
@inline override final def bracketCase[R, E, A, B](
acquire: ZIO[R, E, A]
)(release: (A, BIOExit[E, B]) => ZIO[R, Nothing, Unit]
)(use: A => ZIO[R, E, B]
): ZIO[R, E, B] = {
ZIO.bracketExit[R, E, A, B](acquire, (a, exit) => release(a, ZIOExit.toBIOExit(exit)), use)
}
@inline override final def guaranteeCase[R, E, A](f: ZIO[R, E, A], cleanup: BIOExit[E, A] => ZIO[R, Nothing, Unit]): ZIO[R, E, A] = {
Expand All @@ -81,11 +85,11 @@ class BIOAsyncZio extends BIOAsync3[ZIO] with BIOLocal[ZIO] {
}
@inline override final def racePair[R, E, A, B](
r1: ZIO[R, E, A],
r2: ZIO[R, E, B]
r2: ZIO[R, E, B],
): ZIO[R, E, Either[(A, BIOFiber3[ZIO, E, B]), (BIOFiber3[ZIO, E, A], B)]] = {
(r1.interruptible raceWith r2.interruptible)(
{ case (l, f) => l.fold(f.interrupt *> ZIO.halt(_), ZIOSucceedNow).map(lv => Left((lv, BIOFiber.fromZIO(f)))) },
{ case (r, f) => r.fold(f.interrupt *> ZIO.halt(_), ZIOSucceedNow).map(rv => Right((BIOFiber.fromZIO(f), rv))) }
{ case (r, f) => r.fold(f.interrupt *> ZIO.halt(_), ZIOSucceedNow).map(rv => Right((BIOFiber.fromZIO(f), rv))) },
)
}

Expand All @@ -112,8 +116,10 @@ class BIOAsyncZio extends BIOAsync3[ZIO] with BIOLocal[ZIO] {

@inline override final def uninterruptible[R, E, A](r: ZIO[R, E, A]): ZIO[R, E, A] = r.uninterruptible

@inline override final def parTraverseN[R, E, A, B](maxConcurrent: Int)(l: Iterable[A])(f: A => ZIO[R, E, B]): ZIO[R, E, List[B]] = ZIO.foreachParN(maxConcurrent)(l)(f(_).interruptible)
@inline override final def parTraverseN_[R, E, A, B](maxConcurrent: Int)(l: Iterable[A])(f: A => ZIO[R, E, B]): ZIO[R, E, Unit] = ZIO.foreachParN_(maxConcurrent)(l)(f(_).interruptible)
@inline override final def parTraverseN[R, E, A, B](maxConcurrent: Int)(l: Iterable[A])(f: A => ZIO[R, E, B]): ZIO[R, E, List[B]] =
ZIO.foreachParN(maxConcurrent)(l)(f(_).interruptible)
@inline override final def parTraverseN_[R, E, A, B](maxConcurrent: Int)(l: Iterable[A])(f: A => ZIO[R, E, B]): ZIO[R, E, Unit] =
ZIO.foreachParN_(maxConcurrent)(l)(f(_).interruptible)
@inline override final def parTraverse[R, E, A, B](l: Iterable[A])(f: A => ZIO[R, E, B]): ZIO[R, E, List[B]] = ZIO.foreachPar(l)(f(_).interruptible)
@inline override final def parTraverse_[R, E, A, B](l: Iterable[A])(f: A => ZIO[R, E, B]): ZIO[R, E, Unit] = ZIO.foreachPar_(l)(f(_).interruptible)

Expand All @@ -137,6 +143,6 @@ class BIOAsyncZio extends BIOAsync3[ZIO] with BIOLocal[ZIO] {
@inline override final def andThen[R, R1, E, A](f: ZIO[R, E, R1], g: ZIO[R1, E, A]): ZIO[R, E, A] = f >>> g
@inline override final def asking[R, E, A](f: ZIO[R, E, A]): ZIO[R, E, (A, R)] = f.onFirst

@inline override final def choice[RL, RR, E, A](f: ZIO[RL, E, A], g: ZIO[RR, E, A]): ZIO[Either[RL, RR], E, A] = (f +++ g).map(_.merge)
@inline override final def choice[RL, RR, E, A](f: ZIO[RL, E, A], g: ZIO[RR, E, A]): ZIO[Either[RL, RR], E, A] = (f +++ g).map(_.merge)
@inline override final def choose[RL, RR, E, AL, AR](f: ZIO[RL, E, AL], g: ZIO[RR, E, AR]): ZIO[Either[RL, RR], E, Either[AL, AR]] = f +++ g
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class BIOTemporalZio(private val clock: Clock) extends BIOAsyncZio with BIOTempo
ZIO.sleep(fromScala(duration)).provide(clock)
}

@inline override final def retryOrElse[R, A, E, A2 >: A, E2](r: ZIO[R, E, A])(duration: FiniteDuration, orElse: => ZIO[R, E2, A2]): ZIO[R, E2, A2] =
@inline override final def retryOrElse[R, E, A, E2](r: ZIO[R, E, A])(duration: FiniteDuration, orElse: => ZIO[R, E2, A]): ZIO[R, E2, A] =
ZIO.accessM {
env =>
val zioDuration = Schedule.duration(fromScala(duration))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ sealed trait MiniBIO[+E, +A] {

final class Catcher[E0, A0, E1, B](
val recover: BIOExit.Failure[E0] => MiniBIO[E1, B],
f: A0 => MiniBIO[E1, B]
f: A0 => MiniBIO[E1, B],
) extends (A0 => MiniBIO[E1, B]) {
override def apply(a: A0): MiniBIO[E1, B] = f(a)
}
Expand All @@ -49,7 +49,8 @@ sealed trait MiniBIO[+E, +A] {

case MiniBIO.Sync(a) =>
val exit =
try { a() } catch {
try { a() }
catch {
case t: Throwable =>
BIOExit.Termination(t, Trace.empty)
}
Expand All @@ -58,7 +59,8 @@ sealed trait MiniBIO[+E, +A] {
stack match {
case flatMap :: stackRest =>
val nextIO =
try { flatMap(value) } catch {
try { flatMap(value) }
catch {
case t: Throwable =>
Fail.terminate(t)
}
Expand Down Expand Up @@ -115,30 +117,40 @@ object MiniBIO {

implicit val BIOMiniBIO: BIO[MiniBIO] with BlockingIO[MiniBIO] = new BIO[MiniBIO] with BlockingIO[MiniBIO] {
override def pure[A](a: A): MiniBIO[Nothing, A] = sync(a)
override def flatMap[R, E, A, R1 <: R, E1 >: E, B](r: MiniBIO[E, A])(f: A => MiniBIO[E1, B]): MiniBIO[E1, B] = FlatMap(r, f)
override def flatMap[R, E, A, B](r: MiniBIO[E, A])(f: A => MiniBIO[E, B]): MiniBIO[E, B] = FlatMap(r, f)
override def fail[E](v: => E): MiniBIO[E, Nothing] = Fail(() => BIOExit.Error(v, Trace.empty))
override def terminate(v: => Throwable): MiniBIO[Nothing, Nothing] = Fail.terminate(v)

override def syncThrowable[A](effect: => A): MiniBIO[Throwable, A] = Sync {
() =>
try { BIOExit.Success(effect) } catch { case e: Throwable => BIOExit.Error(e, Trace.empty) }
try {
BIOExit.Success(effect)
} catch { case e: Throwable => BIOExit.Error(e, Trace.empty) }
}
override def sync[A](effect: => A): MiniBIO[Nothing, A] = Sync(() => BIOExit.Success(effect))

override def redeem[R, E, A, E2, B](r: MiniBIO[E, A])(err: E => MiniBIO[E2, B], succ: A => MiniBIO[E2, B]): MiniBIO[E2, B] = {
Redeem[E, A, E2, B](r, {
case BIOExit.Termination(t, e, c) => Fail.halt(BIOExit.Termination(t, e, c))
case BIOExit.Error(e, _) => err(e)
}, succ)
Redeem[E, A, E2, B](
r,
{
case BIOExit.Termination(t, e, c) => Fail.halt(BIOExit.Termination(t, e, c))
case BIOExit.Error(e, _) => err(e)
},
succ,
)
}

override def catchAll[R, E, A, E2, A2 >: A](r: MiniBIO[E, A])(f: E => MiniBIO[E2, A2]): MiniBIO[E2, A2] = redeem(r)(f, pure)
override def catchAll[R, E, A, E2](r: MiniBIO[E, A])(f: E => MiniBIO[E2, A]): MiniBIO[E2, A] = redeem(r)(f, pure)

override def catchSome[R, E, A, E2 >: E, A2 >: A](r: MiniBIO[E, A])(f: PartialFunction[E, MiniBIO[E2, A2]]): MiniBIO[E2, A2] = {
Redeem[E, A, E2, A2](r, {
case BIOExit.Termination(t, e, c) => Fail.halt(BIOExit.Termination(t, e, c))
case exit @ BIOExit.Error(e, _) => f.applyOrElse(e, (_: E) => Fail.halt(exit))
}, pure)
override def catchSome[R, E, A, E2 >: E](r: MiniBIO[E, A])(f: PartialFunction[E, MiniBIO[E2, A]]): MiniBIO[E2, A] = {
Redeem[E, A, E2, A](
r,
{
case BIOExit.Termination(t, e, c) => Fail.halt(BIOExit.Termination(t, e, c))
case exit @ BIOExit.Error(e, _) => f.applyOrElse(e, (_: E) => Fail.halt(exit))
},
pure,
)
}

override def bracketCase[R, E, A, B](acquire: MiniBIO[E, A])(release: (A, BIOExit[E, B]) => MiniBIO[Nothing, Unit])(use: A => MiniBIO[E, B]): MiniBIO[E, B] = {
Expand All @@ -148,7 +160,7 @@ object MiniBIO {
Redeem[E, B, E, B](
io = use(a),
err = e => Redeem[Nothing, Unit, E, Nothing](release(a, e), err = _ => Fail(() => e), succ = _ => Fail(() => e)),
succ = v => map(release(a, BIOExit.Success(v)))(_ => v)
succ = v => map(release(a, BIOExit.Success(v)))(_ => v),
)
)
}
Expand Down
Loading

0 comments on commit 448c40d

Please sign in to comment.