I have 3 distinct modules each with its own error type. Following is a very simplified version.
object ModuleA {
case class ErrorA(msg: String)
def getA: ErrorA \/ String = "1".right
}
object ModuleB {
case class ErrorB(msg: String)
def getB(s: String): ErrorB \/ Int = 1.right
}
object ModuleC {
case class ErrorC(msg: String)
def getC(s: String, i: Int): ErrorC \/ Long = 1L.right
}
As a client of these modules what's the best way to chain these calls.
First - deeply nested, complex return type, but has all the types required.
def call1: ModuleA.ErrorA \/ (ModuleB.ErrorB \/ (ModuleC.ErrorC \/ Long)) = {
ModuleA.getA.map { s =>
ModuleB.getB(s).map { i =>
ModuleC.getC(s, i)
}
}
}
Second - Very readable, but the error types are lost (Inferred return type is Product \/ Long
). Ideally would want something similar with the error types
def call2 =
for {
s <- ModuleA.getA
i <- ModuleB.getB(s)
l <- ModuleC.getC(s, i)
} yield l
Third - Define new error types to encapsulate the existing ones. This seems unfeasible for different combinations
Lastly, tried to use EitherT, but seemed to get complex