1
- //
2
- // USAGE
3
- //
1
+ sealed trait IO [R , E , A ]
2
+
3
+ class Tag [A ]()
4
+
5
+ enum Exit [E , A ]:
6
+ case Fail (e : E )
7
+ case Succeed (a : A )
8
+
9
+ extension [R , E , A ](io : IO [R , E , A ])
10
+ def map [B ](f : A => B ): IO [R , E , B ] = ???
11
+ def flatMap [R2 , E2 , B ](f : A => IO [R2 , E2 , B ]): IO [R2 & R , E2 | E , B ] = ???
12
+ 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 ] = ???
13
+ def inject [R2 , R3 ](r : R2 )(implicit tag : Tag [R2 ], ev : R2 & R3 => R ): IO [R3 , E , A ] = ???
14
+ def catchAll [R2 , E2 , A2 ](f : E => IO [R2 , E2 , A2 ]) = ???
15
+ 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 ] = ???
16
+
17
+ object IO {
18
+ def succeed [A ](a : => A ): IO [Any , Nothing , A ] = ???
19
+ def fail [E ](e : => E ): IO [Any , E , Nothing ] = ???
20
+ def use [R , R2 , E2 , A ](f : R => IO [R2 , E2 , A ])(implicit tag : Tag [R ]): IO [R & R2 , E2 , A ] = ???
21
+ }
4
22
5
23
trait Console {
6
- def putStrLn (msg : => String ): IO [Any , Nothing , Unit ]
24
+ def log (msg : String ): IO [Any , Nothing , Unit ]
7
25
}
8
26
9
27
object Console {
10
28
implicit val tag : Tag [Console ] = Tag ()
11
-
12
- def putStrLn (msg : => String ) = IO use ((T : Console ) => T putStrLn msg)
13
29
}
14
30
15
31
trait Math {
@@ -19,39 +35,15 @@ trait Math {
19
35
object Math {
20
36
implicit val tag : Tag [Math ] = Tag ()
21
37
22
- def add ( x : Int , y : Int ) = IO use (( T : Math ) => T add(x, y))
38
+ val Live : Math = ???
23
39
}
24
40
25
- case class ErrorA (a : String )
26
- case class ErrorB (b : String )
27
-
28
41
val program = for {
29
- _ <- Console putStrLn " hello"
30
- _ <- Console putStrLn " world"
31
- y <- Math add(2 , 3 )
32
- _ <- Console putStrLn s " result: $y"
33
- _ <- IO fail ErrorA (" a" )
34
- _ <- IO fail ErrorB (" b" )
42
+ x <- IO .succeed(1 )
43
+ y <- IO .succeed(2 )
44
+ z <- IO .use((T : Math ) => T .add(x, y))
45
+ _ <- IO .use((T : Console ) => T .log(s " z: ${z}" ))
35
46
} yield ()
36
47
37
- val main = program
38
- .catchSome(e => e match {
39
- case x : ErrorA => (x, Console putStrLn " recovered from A" )
40
- })
41
- .inject(new Console {
42
- def putStrLn (msg : => String ) = IO .succeed(println(msg))
43
- })
44
- .inject(new Math {
45
- def add (x : Int , y : Int ) = IO .succeed(x + y)
46
- })
47
-
48
- @ main def root () = {
49
- main.unsafeRun match {
50
- case Exit .Fail (e) => {
51
- println(" Error:" )
52
- println(e)
53
- ()
54
- }
55
- case Exit .Succeed (a) => ()
56
- }
57
- }
48
+ // CORRECT AS IO[Console, Nothing, Unit]
49
+ val main = program inject Math .Live
0 commit comments