0.2.0 #5
@@ -29,7 +29,14 @@ export const isLens = (u: unknown): u is Lens<unknown, unknown, unknown, unknown
|
||||
|
||||
|
||||
export const LensStepTypeId: unique symbol = Symbol.for("@effect-fc/Lens/LensStep")
|
||||
export type LensStepTypeId = typeof LensTypeId
|
||||
export type LensStepTypeId = typeof LensStepTypeId
|
||||
|
||||
export interface LensFrame<in out A, in out EW = never, in out RW = never> {
|
||||
readonly value: A
|
||||
readonly commit: <E = never, R = never>(
|
||||
next: Effect.Effect<A, E, R>
|
||||
) => Effect.Effect<void, EW | E, RW | R>
|
||||
}
|
||||
|
||||
export interface LensStep<
|
||||
in out A,
|
||||
@@ -44,9 +51,8 @@ export interface LensStep<
|
||||
in out RSW = never,
|
||||
> {
|
||||
readonly [LensStepTypeId]: LensStepTypeId
|
||||
readonly transform: (effect: Effect.Effect<B, ESR, RSR>) => Effect.Effect<A, ER, RR>
|
||||
readonly access: (effect: Effect.Effect<LensFrame<B, ESW, RSW>, ESR, RSR>) => Effect.Effect<LensFrame<A, EW, RW>, ER, RR>
|
||||
readonly transformStream: (stream: Stream.Stream<B, ESR, RSR>) => Stream.Stream<A, ER, RR>
|
||||
readonly update: (next: Effect.Effect<A, ESW, RSW>, parent: B) => Effect.Effect<B, EW, RW>
|
||||
}
|
||||
|
||||
export const isLensStep = (u: unknown): u is LensStep<unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown> => Predicate.hasProperty(u, LensStepTypeId)
|
||||
@@ -89,11 +95,23 @@ extends Pipeable.Class() implements Lens<A, ER, EW, RR, RW> {
|
||||
abstract readonly sourceCommit: (b: B) => Effect.Effect<void, ESW, RSW>
|
||||
abstract readonly withLock: <A1, E1, R1>(self: Effect.Effect<A1, E1, R1>) => Effect.Effect<A1, EW | E1, RW | R1>
|
||||
|
||||
get get(): Effect.Effect<A, ER, RR> {
|
||||
let effect: Effect.Effect<unknown, unknown, unknown> = this.sourceGet
|
||||
private get access(): Effect.Effect<LensFrame<A, EW, RW>, ER, RR> {
|
||||
let effect: Effect.Effect<LensFrame<unknown, unknown, unknown>, unknown, unknown> = Effect.map(
|
||||
this.sourceGet,
|
||||
value => ({
|
||||
value,
|
||||
commit: next => Effect.flatMap(next, value => this.sourceCommit(value as B)),
|
||||
}),
|
||||
)
|
||||
|
||||
for (const step of this.steps)
|
||||
effect = step.transform(effect)
|
||||
return effect as Effect.Effect<A, ER, RR>
|
||||
effect = step.access(effect as never) as Effect.Effect<LensFrame<unknown, unknown, unknown>, unknown, unknown>
|
||||
|
||||
return effect as Effect.Effect<LensFrame<A, EW, RW>, ER, RR>
|
||||
}
|
||||
|
||||
get get(): Effect.Effect<A, ER, RR> {
|
||||
return Effect.map(this.access, frame => frame.value)
|
||||
}
|
||||
|
||||
get changes(): Stream.Stream<A, ER, RR> {
|
||||
@@ -107,38 +125,12 @@ extends Pipeable.Class() implements Lens<A, ER, EW, RR, RW> {
|
||||
f: (a: A) => Effect.Effect<readonly [C, A], E1, R1>,
|
||||
): Effect.Effect<C, ER | EW | E1, RR | RW | R1> {
|
||||
return this.withLock(Effect.flatMap(
|
||||
this.sourceGet,
|
||||
source => {
|
||||
const parents: unknown[] = []
|
||||
let current: Effect.Effect<unknown, unknown, unknown> = Effect.succeed(source)
|
||||
|
||||
for (const step of this.steps)
|
||||
current = Effect.flatMap(current, parent => {
|
||||
parents.push(parent)
|
||||
return step.transform(Effect.succeed(parent))
|
||||
})
|
||||
|
||||
return Effect.flatMap(current, a => Effect.flatMap(
|
||||
f(a as A),
|
||||
([c, next]) => {
|
||||
let rebuilt: Effect.Effect<unknown, unknown, unknown> = Effect.succeed(next)
|
||||
|
||||
for (let i = this.steps.length - 1; i >= 0; i--) {
|
||||
// biome-ignore lint/style/noNonNullAssertion: won't throw
|
||||
const step = this.steps[i]!
|
||||
// biome-ignore lint/style/noNonNullAssertion: won't throw
|
||||
const parent = parents[i]!
|
||||
rebuilt = step.update(rebuilt, parent)
|
||||
}
|
||||
|
||||
return Effect.as(
|
||||
Effect.flatMap(rebuilt, b => this.sourceCommit(b as B)),
|
||||
c,
|
||||
)
|
||||
},
|
||||
this.access,
|
||||
frame => Effect.flatMap(
|
||||
f(frame.value),
|
||||
([c, next]) => Effect.as(frame.commit(Effect.succeed(next)), c),
|
||||
),
|
||||
))
|
||||
},
|
||||
)) as Effect.Effect<C, ER | EW | E1, RR | RW | R1>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user