@@ -14,55 +14,57 @@ end boundary
14
14
15
15
import boundary .{Label , break }
16
16
17
- class Async
17
+ @ capability trait Async
18
+ object Async :
19
+ def blocking [T ](body : Async ?=> T ): T = ???
20
+
18
21
class Future [+ T ]:
19
22
this : Future [T ]^ =>
20
- def await (using Async ^ ): T = ???
23
+ def await (using Async ): T = ???
21
24
object Future :
22
- def apply [T ](op : Async ^ ?=> T )(using Async ): Future [T ]^ {op} = ???
25
+ def apply [T ](op : Async ?=> T )(using Async ): Future [T ]^ {op} = ???
26
+
27
+ enum Result [+ T , + E ]:
28
+ case Ok [+ T ](value : T ) extends Result [T , Nothing ]
29
+ case Err [+ E ](error : E ) extends Result [Nothing , E ]
23
30
24
- abstract class Result [+ T , + E ]
25
- case class Ok [+ T ](value : T ) extends Result [T , Nothing ]
26
- case class Err [+ E ](value : E ) extends Result [Nothing , E ]
27
31
28
32
object Result :
29
- extension [T , E ](r : Result [T , E ])
33
+ extension [T , E ](r : Result [T , E ]^ )( using Label [ Err [ E ]] )
30
34
31
35
/** `_.ok` propagates Err to current Label */
32
- inline def ok ( using Label [ Result [ Nothing , E ]]) : T = r match
33
- case r : Ok [_] => r. value
34
- case err => break(err. asInstanceOf [Err [E ]])
36
+ def ok : T = r match
37
+ case Ok (value) => value
38
+ case Err (value) => break[Err [E ]]( Err (value) )
35
39
36
40
transparent inline def apply [T , E ](inline body : Label [Result [T , E ]] ?=> T ): Result [T , E ] =
37
- boundary :
38
- val result = body
39
- Ok (result)
41
+ boundary(Ok (body))
40
42
41
43
// same as apply, but not an inline method
42
44
def make [T , E ](body : Label [Result [T , E ]] ?=> T ): Result [T , E ] =
43
- boundary :
44
- val result = body
45
- Ok (result)
45
+ boundary(Ok (body))
46
46
47
47
end Result
48
48
49
49
def test [T , E ](using Async ) =
50
- val good1 : List [Future [Result [T , E ]]] => Future [Result [List [T ], E ]] = frs =>
51
- Future :
52
- Result :
53
- frs.map(_.await.ok) // OK
50
+ import Result .*
51
+ Async .blocking: async ?=>
52
+ val good1 : List [Future [Result [T , E ]]] => Future [Result [List [T ], E ]] = frs =>
53
+ Future :
54
+ Result :
55
+ frs.map(_.await.ok) // OK
54
56
55
- val good2 : Result [Future [T ], E ] => Future [Result [T , E ]] = rf =>
56
- Future :
57
- Result :
58
- rf.ok.await // OK, Future argument has type Result[T]
57
+ val good2 : Result [Future [T ], E ] => Future [Result [T , E ]] = rf =>
58
+ Future :
59
+ Result :
60
+ rf.ok.await // OK, Future argument has type Result[T]
59
61
60
- def fail3 (fr : Future [Result [T , E ]]^ ) =
61
- Result :
62
- Future : // error, escaping label from Result
63
- fr.await.ok
62
+ def fail3 (fr : Future [Result [T , E ]]^ ) =
63
+ Result :
64
+ Future : // error, escaping label from Result
65
+ fr.await.ok
64
66
65
- def fail4 (fr : Future [Result [T , E ]]^ ) =
66
- Result .make: // error, escaping label from Result
67
- Future :
68
- fr.await.ok
67
+ def fail4 [ T , E ] (fr : Future [Result [T , E ]]^ ) =
68
+ Result .make: // lbl ?=> // error, escaping label from Result
69
+ Future : fut ?=>
70
+ fr.await.ok
0 commit comments