Feature Request: When tap is not enough: execute
seprich opened this issue · comments
The inferred signature of tap
(and its relatives tapOk
, tapError
) are as follows:
let tap: (Future.t('a), 'a => unit) => Future.t('a);
let tapOk: (Future.t(Belt.Result.t('a, 'e)), 'a => 'z) => Future.t(Belt.Result.t('a, 'e));
let tapError: (Future.t(Belt.Result.t('a, 'e)), 'e => 'z) => Future.t(Belt.Result.t('a, 'e));
These functions do have the limitation that the side-effect function signature 'e => unit
does not allow any async operations such as committing or rollbacking RDB transactions ; such operations would require 'a => Future.t(unit)
type of signatures. In other words the execution chain should wait for the side-effect to become ready before continuing. Therefore I would propose the following additions to this library:
let execute: (Future.t('a), 'a => Future.t(unit)) => Future.t('a)
let executeOk: (Future.t(Belt.Result.t('a, 'e)), 'a => Future.t(Belt.Result.t(unit, 'e))) => Future.t(Belt.Result.t('a, 'e));
let executeError: (Future.t(Belt.Result.t('a, 'e)), 'e => Future.t(Belt.Result.t(unit, 'e))) => Future.t(Belt.Result.t('a, 'e));
These variants would execute the side effect function before continuing. In the basic case of execute
the given function doesn't contribute any values to the chain - return value matches the 1st parameter exactly. For executeOk
and executeError
I am proposing a bit more complicated behavior:
- In the
executeOk
the original Ok and Error values are preserved except if the given function results in error in which case that error overrides the original ok result. The rationale here is that usually we do not want to just ignore problems that happened when executed a side-effect. - The
executeError
is similar to the previous: The original Ok and Error values are preserved except if the given function results in Error which will override the original Error.