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