Closed
Description
What is the problem this feature would solve?
Given an Option<A>
and a fn (a: A) => Effect<B, E, R>
it would be useful to have a function that could apply that fn to the Some value and return an Effect<Option<B>, E, R>
rather than an Option<Effect<B, E, R>>
as Option.map
would so that it can more easily be used in an effect pipeline.
This is a pattern I am coming across a few times when, for example, decoding from a database query where the potential for a missing row is represented as an Option
What is the feature you are proposing to solve the problem?
Option.mapEffect seems like a fairly obvious api for this I think, I have made my own function to do this:
import { Effect, Option } from 'effect';
import { dual } from 'effect/Function';
export const mapEffect: {
<B, A, E, R>(
f: (a: A) => Effect.Effect<B, E, R>,
): (self: Option.Option<A>) => Effect.Effect<Option.Option<B>, E, R>;
<B, A, E, R>(
self: Option.Option<A>,
f: (a: A) => Effect.Effect<B, E, R>,
): Effect.Effect<Option.Option<B>, E, R>;
} = dual(2, <B, A, E, R>(self: Option.Option<A>, f: (a: A) => Effect.Effect<B, E, R>) =>
Option.match(self, {
onSome: (value) => Effect.map(f(value), Option.some),
onNone: () => Effect.succeedNone,
}),
);
What alternatives have you considered?
- Using my own wrapper as posted
- Using no wrapper and just writing out the relatively verbose
Effect.andThen(Option.match( ... ))
- A more generic 'transpose' function (as rust calls it) that would take
Option<Effect<A, E, R>>
and turn it intoEffect<Option<A>, E, R>
. Then you could use the existing option map in a pipeline like:(..., Effect.map(Option.map(fn)), Effect.andThen(Option.transpose)
. I think this would be super useful and am slightly surprised I couldn't find a similar function in effect.