-
-
Notifications
You must be signed in to change notification settings - Fork 272
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Option.mapEffect #3142
Comments
@jamesbirtles - thank you for opening the issue and providing a very detailed description of the use case! Given that Going to close this issue as the requested functionality essentially already exists in the library and it is unlikely that we will add a |
+1 this seems obvious to me. The name |
i must admit I am also not super satisfied with the I very often end up in a scenario like this: // I have some effect of type `Effect.Effect<Option.Option<A>, E, R>`;
const effect = Effect.succeedSome(1);
// Oh now I want to simply map the `A`, guess I'm doing this rigmarole again
effect.pipe(
// Flatten to `Effect.Effect<A, E | Cause.NoSuchElementException, R>`
Effect.flatten,
// Do the thing I actually wanted to do (imagining this was some operation that required it to be an effect)
Effect.andThen((x) => Effect.succeed(x + 1)),
// now back to what I actually want, I hope there's no other `Cause.NoSuchElementException` I'm accidentally capturing here
Effect.optionFromOptional
); given that Effect is clearly not adverse to having technically duplicate functionality but with nicer ergonomics based on the million and one functions it already has, I am somewhat surprised that there is a lack of desire to make this (imo very common) use case more ergonomic and discoverable |
@jamesbirtles - in the past, we did have an Having But IIRC, the main reason we removed these types of methods was that it was very difficult to draw the line for where to stop adding them, so we opted for providing the functionality within the Having said the above, I do agree that we can probably do better on naming in this particular case. I'll re-open the issue and summon @mikearnaldi, @gcanti, and @tim-smart to further discuss. |
I would like to just add my 2 c. Imo, you have to think about target audience, general direction, and convenience. I don't think bundle size is that important to most Effect users. Second, Effect has the task of becoming popular, and that's not going to happen by worrying about pennies of bundle size, but by building libraries that are convenient and useful. But I'm just giving my 2 c, I'm a just a little guy here. I'm very thankful for everything you're building and built either way :) |
I'm not sure if "mapEffect" is a good name since there are multiple Swapping data types inside out is commonly named as follows:
p.s. |
@gcanti that's sort of the direction that @jamesbirtles suggested:
I'm +1 for |
This is my version of transpose if want to copy past in your projects: export const transpose = <A, E, R>(
param: Option.Option<Effect.Effect<A, E, R>>,
): Effect.Effect<Option.Option<A>, E, R> => {
return param.pipe(
Option.match({
onNone: () => Effect.succeedNone,
onSome: Effect.flatMap(Effect.succeedSome),
}),
);
}; |
@titouancreach I think adding defaults to type parameters would help handle import { Option, Effect } from "effect"
declare const transpose: <A, E, R>(
param: Option.Option<Effect.Effect<A, E, R>>
) => Effect.Effect<Option.Option<A>, E, R>
// const x: Effect.Effect<Option.Option<unknown>, unknown, unknown>
const x = transpose(Option.none())
declare const transposeWithDefaults: <A = never, E = never, R = never>(
param: Option.Option<Effect.Effect<A, E, R>>
) => Effect.Effect<Option.Option<A>, E, R>
// const y: Effect.Effect<Option.Option<never>, never, never>
const y = transposeWithDefaults(Option.none()) |
@gcanti Totally agree ! thanks |
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 anEffect<Option<B>, E, R>
rather than anOption<Effect<B, E, R>>
asOption.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:
What alternatives have you considered?
Effect.andThen(Option.match( ... ))
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.The text was updated successfully, but these errors were encountered: