effect icon indicating copy to clipboard operation
effect copied to clipboard

Option.mapEffect

Open jamesbirtles opened this issue 1 year ago • 0 comments

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 into Effect<Option<A>, E, R>. Then you could use the existing option map in a pipeline like: (..., Effect.andThen(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.

jamesbirtles avatar Jul 02 '24 10:07 jamesbirtles