-
Notifications
You must be signed in to change notification settings - Fork 95
/
Copy patherror.scala
93 lines (80 loc) · 4.61 KB
/
error.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package tofu
package syntax
import cats.{Applicative, Functor, Monad}
import cats.ApplicativeError
object raise {
//** special alias for Raise[F, E] for use in situations when F[_] can be unknown from the start */
type FindRaise[E] = FindRaise.Search[E]
object FindRaise extends FindRaiseLowPrio {
trait Find[E] extends Any
type Search[E] = AnyRef with Find[E] { type Eff[_] }
type Aux[E, F[_]] = FindRaise[E] { type Eff[a] = F[a] }
def wrap[F[_], E](r: Raise[F, E]): Aux[E, F] = r.asInstanceOf[Aux[E, F]]
def unwrap[F[_], E](r: Aux[E, F]): Raise[F, E] = r.asInstanceOf[Raise[F, E]]
implicit final def findByApplicativeError[F[_], E1, E](implicit
app: ApplicativeError[F, E],
evE: E1 <:< E
): Aux[E1, F] = wrap(implicitly)
}
trait FindRaiseLowPrio {
implicit final def findByRaise[F[_], E1, E](implicit
app: Raise[F, E],
evE: E1 <:< E
): FindRaise.Aux[E1, F] = FindRaise.wrap(implicitly)
}
implicit final class RaiseOps[E](private val err: E) extends AnyVal {
def raise[F[_], A](implicit raise: FindRaise.Aux[E, F]): F[A] = FindRaise.unwrap(raise).raise(err)
}
implicit final class RaiseMonadOps[F[_], A](private val fa: F[A]) extends AnyVal {
def verified[E](p: A => Boolean)(err: E)(implicit raise: Raise[F, E], F: Monad[F]): F[A] =
F.flatMap(fa)(a => if (p(a)) F.pure(a) else raise.raise(err))
}
implicit final class RaiseOptionOps[A](private val opt: Option[A]) extends AnyVal {
// name changed from `liftTo` to avoid conflicts with cats.syntax.option
def orRaise[F[_]] = new RaiseOptionApplied[F, A](opt)
}
implicit final class RaiseEitherOps[E, A](private val either: Either[E, A]) extends AnyVal {
def toRaise[F[_]](implicit
app: Applicative[F],
raise: FindRaise.Aux[E, F]
): F[A] =
either match {
case Left(err) => FindRaise.unwrap(raise).raise(err)
case Right(value) => app.pure(value)
}
}
class RaiseOptionApplied[F[_], A](val opt: Option[A]) extends AnyVal {
def apply[E](err: => E)(implicit raise: FindRaise.Aux[E, F], app: Applicative[F]): F[A] =
opt match {
case None => FindRaise.unwrap(raise).raise(err)
case Some(a) => app.pure(a)
}
}
}
object handle {
implicit final class HandleOps[F[_], A](private val fa: F[A]) extends AnyVal {
def restore(implicit FE: RestoreTo[F, F]): F[Option[A]] = FE.restore(fa)
def restoreTo[G[_]](implicit FE: RestoreTo[F, G]): G[Option[A]] = FE.restore(fa)
def restoreWith(ra: => F[A])(implicit FE: Restore[F]): F[A] = FE.restoreWith(fa)(ra)
def retry(count: Int)(implicit FE: Restore[F]): F[A] = if (count <= 1) fa else restoreWith(retry(count - 1))
def retryOnly[E](count: Int)(implicit FE: Handle[F, E]): F[A] =
if (count <= 1) fa else handleWith[E](_ => retryOnly[E](count - 1))
def handleWith[E](f: E => F[A])(implicit FE: Handle[F, E]): F[A] = FE.handleWith(fa)(f)
def handleToWith[G[_], E](f: E => G[A])(implicit FE: HandleTo[F, G, E]): G[A] = FE.handleWith(fa)(f)
def tryHandleWith[E](f: E => Option[F[A]])(implicit FE: Handle[F, E]): F[A] = FE.tryHandleWith(fa)(f)
def tryHandle[E](f: E => Option[A])(implicit F: Applicative[F], FE: Handle[F, E]): F[A] = FE.tryHandle(fa)(f)
def handle[E](f: E => A)(implicit FE: Handle[F, E], F: Applicative[F]): F[A] = FE.handle(fa)(f)
def handleTo[G[_]: Applicative, E](f: E => A)(implicit FE: HandleTo[F, G, E]): G[A] = FE.handle(fa)(f)
def recoverWith[E](pf: PartialFunction[E, F[A]])(implicit FE: Handle[F, E]): F[A] = FE.recoverWith(fa)(pf)
def recover[E](pf: PartialFunction[E, A])(implicit F: Applicative[F], FE: Handle[F, E]): F[A] = FE.recover(fa)(pf)
def attempt[E](implicit F: Applicative[F], FE: Handle[F, E]): F[Either[E, A]] = FE.attempt(fa)
def attemptTo[G[_]: Applicative, E](implicit F: Functor[F], FE: HandleTo[F, G, E]): G[Either[E, A]] = FE.attempt(fa)
def onError[B, E](f: E => F[B])(implicit FE: Errors[F, E], F: Applicative[F]): F[A] =
FE.handleWith(fa)(e => F.productR(f(e))(FE.raise(e)))
}
}
object error {
implicit final class ErrorOps[F[_], A](private val fa: F[A]) extends AnyVal {
def adaptError[E](pf: PartialFunction[E, E])(implicit FE: Errors[F, E]): F[A] = FE.adaptError(fa)(pf)
}
}