When replacing handleError with recover calls, I s...
# arrow
o
When replacing handleError with recover calls, I stumble upon this problem: in some situations, an error state needed to be thrown as an exception to the caller. So this code is quite common in several places:
Copy code
fun <A> Either<String, A>.orThrow() =
        handleError { error(it) }
When replacing the handleError with a straight forward recover call, as the Deprecation annotation suggests, I get a "Not enough information to infer type variable EE" compilation error. Somehow the recover function wants to know its raise error type, even though this should be unnecessary here... Because recover has three Generics, all of them need to be put in place, which is really not pretty...
Copy code
fun <A> Either<String, A>.orThrow() =
        recover<String, Nothing, A> { error(it) }
Another really strange finding regarding the RaiseDSL is this one:
Copy code
fun <A> demo(a: EitherNel<String, A>): Either<String, Int> =
        either {
            a.bind()
            error("BOOM")
        }.recover { 12 }
The Kotlin compiler warns that the recover is "unreachable code" - which it is not. It will be executed when the argument a is a Left... strange, don't you think?
s
The first two examples are indeed a bit sad, I was actually quite disappointed that Kotlin couldn't infer
Nothing
when the
@BuilderInference
is unused, and overloading this function with only 2 type params results in "ambiguous overload". It's something I tried, and Kotlin allows you to define both methods but then fails to resolve the correct function at the call-site. 😞 Both can be solved by providing an explicit return type for the function, instead of having it resolved though.
The latter I also noticed last week, and it's IMO a false negative from the compiler because there is no way the compiler can actually figure that out correctly... 🤔 Curious if this is due to the fact that we added
contract
to the definition of
either
... It still seems like a false negative, not sure if we can resolve that somehow 🤔 This was working correctly before, but not sure if
contract
introduced this or if it's a bug in 1.8.x. I haven't checked yet.