I was using the raise DSL for something that ended...
# arrow
s
I was using the raise DSL for something that ended up returning an Either. I now realized I want to be able to return both errors and data at the same time, making me look into Ior instead of Either for the return type. I feel that
iorNel {}
is the equivalent of doing
raise {}
in this context, since I want to be able to return many errors in a Nel if many such errors arise. Inside the dsl, I was hoping I could do something like
Copy code
iorNel<ErrorType, DataType> {
  raise(ErrorType("1")) // Was looking for smth other than raise here, but there isn't something as far as I can tell, so writing raise just to show what I mean
  raise(ErrorType("2"))
  DataType()
}
and end up with a
Copy code
Ior.Both(
  [ErrorType("1"), ErrorType("2")],
  DataType()
)
But it does not look like that's how it's supposed to be used.
raise
still short-circuits, and I do not seem to see a way to "accumulate" such errors while in this DSL. Am I missing something perhaps which makes this possible? The
internal fun combine(e: Error): Error = state.updateAndGet { EmptyValue.combine(it, e, combineError) } as Error
function is internal in the
IorRaise
scope. Is the only possible API for me to do this instead?
Copy code
iorNel<ErrorType, DataType> {
  val ignored = Ior.Both(ErrorType("1")).nel(), DataType("This is ignored anyway")).bind()
  val ignored = Ior.Both(ErrorType("2")).nel(), DataType("This is ignored too")).bind()
  DataType()
}
Any hints here would be quite welcome
👀 2
a
we're actually bringing a new API for this specific use case in Arrow 2.0, which hopefully will be released soon
Copy code
accumulate(ErrorType("1").nel())
in the meantime my suggestion is for you to define your own version
Copy code
fun <E, A> IorRaise<E, A>.accumulate(value: E): Unit =
  Ior.Both(value, Unit).bind()
s
Yeah it would be amazing to have something build in there! The shape of it that I like the most ended up being
Copy code
private fun <E> IorRaise<Nel<E>>.accumulate(value: E): Unit = Ior.Both(value.nel(), Unit).bind()
Since I actually would also like to be able to avoid having to do the
.nel()
on the error type anyway, since in the end I always want the errors to accumulate inside the Nel anyway. This looks super slick tbh, the migration is also just changing the scope and replacing
raise
with
accumulate
and that was more or less it I think. Thanks for the quick response, and looking forward to the API in 2.x!
I did feel the need to also add a
Copy code
private fun <E> IorRaise<Nel<E>>.raise(value: E): Unit = raise(value.nel())
because doing the
.nel()
feels redundant there too when I do in fact want to short-circuit with a single error, despite the return type for the error being a nel, I do like knowing that I can just raise with 1 item and know that it will be added to the nel automatically. Have you had this feeling as well when perhaps working with this? Or have had people mention this before?
1
a
yeah, this has been requested for any
Raise<Nel<E>>
... but unfortunately right now we cannot provide this because you cannot have a extension for
Raise<E>
and the same one for
Raise<Nel<E>>
due to erasure...
s
Ah erasure, oops 😅
r
@Alejandro Serrano.Mena, do you have a link to the branch containing the preview of this feature?
a
you mean the
accumulate
for Ior? It's just in
main
🙏 1