1
+ package theproblem
2
+
3
+ import scala .concurrent .{ ExecutionContext , Future }
4
+ import scala .concurrent .ExecutionContext .Implicits .global
5
+
6
+ object Items :
7
+ opaque type TheId = Int
8
+ extension (TheId : TheId ) def raw : Int = TheId
9
+
10
+ object TheId :
11
+ def apply (id : Int ): TheId = id
12
+
13
+
14
+ import Items .TheId
15
+
16
+ case class AnError (id : TheId )
17
+
18
+ type ErrAcc [A ] = Either [Seq [AnError ], A ]
19
+
20
+ case class Res [A ](future : Future [ErrAcc [A ]]):
21
+
22
+ def map [B ](f : A => B )(using ExecutionContext ): Res [B ] =
23
+ Res (this .future.map(_.map(f)))
24
+
25
+ def flatMap [B ](f : A => Res [B ])(using ExecutionContext ): Res [B ] =
26
+ Res (this .future.flatMap {
27
+ case Right (x) => f(x).future
28
+ case Left (es) => Future .successful(Left [Seq [AnError ], B ](es))
29
+ })
30
+
31
+ def zip [B ](that : Res [B ])(using ExecutionContext ): Res [(A , B )] =
32
+ def zipacc (a : ErrAcc [A ], b : ErrAcc [B ]): ErrAcc [(A , B )] = (a, b) match
33
+ case (Right (x), Right (y)) => Right ((x, y))
34
+ case (Right (_), Left (e) ) => Left (e)
35
+ case (Left (e), Right (_)) => Left (e)
36
+ case (Left (ex), Left (ey)) => Left (ex ++ ey)
37
+
38
+ Res (this .future.flatMap { a => that.future.map { b => zipacc(a, b) } })
39
+
40
+ object Res :
41
+ def successful [A ](x : A ): Res [A ] = Res (Future .successful(Right [Seq [AnError ], A ](x)))
42
+
43
+ def traverse [A , B ](as : Seq [A ])(f : A => Res [B ])(using ExecutionContext ): Res [Seq [B ]] =
44
+ as.foldLeft[Res [Seq [B ]]](successful(Seq .empty)) { (acc, x) => acc.zip(f(x)).map(_ :+ _) }
45
+
46
+ trait M :
47
+ def getID (name : String )(using ExecutionContext ): Res [TheId ]
48
+ def bfs (sid : TheId , tid : TheId ): Res [Boolean ]
49
+
50
+ class theproblem (m : M ):
51
+
52
+ def thebug (names : List [String ]): Res [Seq [(String , String , Boolean )]] =
53
+ Res .traverse(names)(m.getID).flatMap { ids =>
54
+ val id_names = ids.zip(names)
55
+ val ps = for {
56
+ (sid, sname) <- id_names
57
+ (tid, tname) <- id_names
58
+ if sid != tid
59
+ } yield (sid -> sname, tid -> tname)
60
+ Res .traverse(ps){ (s, t) =>
61
+ m.bfs(s(0 ), t(0 )).map((s(1 ), t(2 ), _)) // error t(2) should be t(1)
62
+ }
63
+ }
0 commit comments