Add mapOptionEffect
All checks were successful
Lint / lint (push) Successful in 12s

This commit is contained in:
Julien Valverdé
2026-03-28 20:57:48 +01:00
parent 2328e1fc3d
commit 12ed1125f0

View File

@@ -213,6 +213,42 @@ export const mapOption: {
}),
))
/**
* Derives a new `Lens` by applying effectful getters and setters over the value inside an `Option`.
*
* Similar to `Option.map`, this preserves the `Option` structure:
* - If the `Option` is `Some(a)`, applies the effectful getter and setter to the inner value
* - If the `Option` is `None`, it remains `None`
*/
export const mapOptionEffect: {
<A, ER, EW, RR, RW, B, EGet = never, RGet = never, ESet = never, RSet = never>(
self: Lens<Option.Option<A>, ER, EW, RR, RW>,
get: (a: NoInfer<A>) => Effect.Effect<B, EGet, RGet>,
set: (a: NoInfer<A>, b: B) => Effect.Effect<NoInfer<A>, ESet, RSet>,
): Lens<Option.Option<B>, ER | EGet, EW | ESet, RR | RGet, RW | RSet>
<A, ER, EW, RR, RW, B, EGet = never, RGet = never, ESet = never, RSet = never>(
get: (a: NoInfer<A>) => Effect.Effect<B, EGet, RGet>,
set: (a: NoInfer<A>, b: B) => Effect.Effect<NoInfer<A>, ESet, RSet>,
): (self: Lens<Option.Option<A>, ER, EW, RR, RW>) => Lens<Option.Option<B>, ER | EGet, EW | ESet, RR | RGet, RW | RSet>
} = Function.dual(3, <A, ER, EW, RR, RW, B, EGet = never, RGet = never, ESet = never, RSet = never>(
self: Lens<Option.Option<A>, ER, EW, RR, RW>,
get: (a: NoInfer<A>) => Effect.Effect<B, EGet, RGet>,
set: (a: NoInfer<A>, b: B) => Effect.Effect<NoInfer<A>, ESet, RSet>,
): Lens<Option.Option<B>, ER | EGet, EW | ESet, RR | RGet, RW | RSet> => mapEffect(
self,
Option.match({
onSome: a => Effect.map(get(a), Option.some),
onNone: () => Effect.succeed(Option.none()),
}),
(opt, newOpt) => Option.match(opt, {
onSome: a => Option.match(newOpt, {
onSome: b => Effect.map(set(a, b), Option.some),
onNone: () => Effect.succeed(Option.none()),
}),
onNone: () => Effect.succeed(Option.none()),
}),
))
/**
* Allows transforming only the `changes` stream of a `Lens` while keeping the focus type intact.
*/