Skip to content

Commit 423c61c

Browse files
committed
implement catchSome
1 parent fbdc12d commit 423c61c

File tree

2 files changed

+24
-7
lines changed

2 files changed

+24
-7
lines changed

src/main/scala/IO.scala

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,21 @@
11
enum IO[-R, +E, +A]:
22
def map[B](f: A => B): IO[R, E, B] = this.flatMap(a => IO.succeed(f(a)))
33

4+
def flatMap[R2, E2, B](f: A => IO[R2, E2, B]): IO[R2 & R, E2 | E, B] = IO.FlatMap(this, f)
5+
6+
def foldM[R2, E2, A2, R3, E3, A3](f: A => IO[R2, E2, A2], g: E => IO[R3, E3, A3]): IO[R3 & R2 & R, E3 | E2, A3 | A2] = IO.Fold(this, f, g)
7+
8+
def inject[R2, R3](r: R2)(implicit tag: Tag[R2], ev: R2 & R3 => R): IO[R3, E, A] = IO.Provide(this, r, tag, ev)
9+
10+
def catchAll[R2, E2, A2](f: E => IO[R2, E2, A2]) = this.foldM(IO.succeed, f)
11+
12+
def catchSome[R2, E2, A2, E3, E4](f: PartialFunction[E, (E3, IO[R2, E2, A2])])(implicit ev: E => E3 | E4): IO[R & R2, E2 | E4, A | A2] = this.foldM(IO.succeed, e => {
13+
f.lift(e) match {
14+
case Some((e3, io)) if e3 == e => io
15+
case _ => IO.fail(ev(e).asInstanceOf[E4])
16+
}
17+
})
18+
419
case Succeed[A](
520
val a: () => A
621
) extends IO[Any, Nothing, A]
@@ -29,10 +44,6 @@ enum IO[-R, +E, +A]:
2944

3045
class Tag[A]()
3146

32-
extension [R, E, A](zio: IO[R, E, A])
33-
def flatMap[R2, E2, B](f: A => IO[R2, E2, B]): IO[R2 & R, E2 | E, B] = IO.FlatMap(zio, f)
34-
def inject[R2, R3](r: R2)(implicit tag: Tag[R2], ev: R2 & R3 => R): IO[R3, E, A] = IO.Provide(zio, r, tag, ev)
35-
3647
enum Exit[+E, +A]:
3748
case Fail(e: E)
3849
case Succeed(a: A)
@@ -49,7 +60,6 @@ extension [E, A](zio: IO[Any, E, A])
4960
var cont = List[ContiuationFrame]()
5061
var services = Map[Tag[Any], Any]()
5162

52-
// recursing
5363
var recursing = true
5464

5565
while (recursing) {
@@ -136,6 +146,8 @@ extension [E, A](zio: IO[Any, E, A])
136146

137147
object IO {
138148
def succeed[A](a: => A): IO[Any, Nothing, A] = Succeed(() => a)
149+
139150
def fail[E](e: => E): IO[Any, E, Nothing] = Fail(() => e)
151+
140152
def use[R, R2, E2, A](f: R => IO[R2, E2, A])(implicit tag: Tag[R]): IO[R & R2, E2, A] = Use(f, tag)
141153
}

src/main/scala/Main.scala

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ trait Console {
99
object Console {
1010
implicit val tag: Tag[Console] = Tag()
1111

12-
def putStrLn(msg: => String) = IO use ((c: Console) => c putStrLn msg)
12+
def putStrLn(msg: => String) = IO use ((T: Console) => T putStrLn msg)
1313
}
1414

1515
trait Math {
@@ -19,7 +19,7 @@ trait Math {
1919
object Math {
2020
implicit val tag: Tag[Math] = Tag()
2121

22-
def add(x: Int, y: Int) = IO use ((c: Math) => c add(x, y))
22+
def add(x: Int, y: Int) = IO use ((T: Math) => T add(x, y))
2323
}
2424

2525
case class ErrorA(a: String)
@@ -30,9 +30,14 @@ val program = for {
3030
_ <- Console putStrLn "world"
3131
y <- Math add(2, 3)
3232
_ <- Console putStrLn s"result: $y"
33+
_ <- IO fail ErrorA("a")
34+
_ <- IO fail ErrorB("b")
3335
} yield ()
3436

3537
val main = program
38+
.catchSome(e => e match {
39+
case x: ErrorA => (x, Console putStrLn "recovered from A")
40+
})
3641
.inject(new Console {
3742
def putStrLn(msg: => String) = IO.succeed(println(msg))
3843
})

0 commit comments

Comments
 (0)