relude-reason-react
relude-reason-react copied to clipboard
Change the IO-based actions to require an `IO.t(action, Void.t)`
@mlms13 pointed out that sometimes you do IO-based updates in a reducer (UpdatedWithIO
, etc.), but the IO
can't fail (has an error type of Void.t
). The framework is requiring you to return an IO.t(action, action)
right now, and I did that mainly for convenience, but it probably makes sense to change the expected type to IO.t(action, Void.t)
to indicate that you have handled the errors (by changing them to a successful action), and to also allow for IO
actions that can't fail.
This would be a breaking change, and would require users to update their code everywhere, but the change should be very simple to make. I.e. using IO.handleError
.
Yeah, this came up when I was working on random generators, which produce values inside IO, but the effect can't fail. On the other hand mapError(absurd)
made me feel really cool. :)
I think the IO.t(action, action)
came about before handleError
was a thing, but with that function being just as easy to use as mapError
now, I think it makes sense to require a void error channel.
I know I've mostly used bimap
to convert the IO values to actions, so we could add a helper function to IO
like mapHandleError
which lets' you map
and handleError
at the same time. This way, people who were using bimap
could fix their code by just changing that function name.
let mapHandleError: 'a 'e 'b. ('a => 'b, 'e => 'b, IO.t('a, 'e)) => IO.t('b, Void.t)
Name suggestions welcome... mapHandleError
/mapHandle
?... maybe ZIO
has a function like this we can copy.
The same function would also make sense for other bifunctors like Result
and Validation
, so it could live in BifunctorExtensions
but it gets a little tricky b/c this implies success/fail semantics, but bifunctor doesn't necessarily impose those same semantics. I would probably just put the function in each of the modules and not try to make it an extension.
mapHandleError
function was added in relude v0.54.0