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 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<
|
export interface LensStep<
|
||||||
in out A,
|
in out A,
|
||||||
@@ -44,9 +51,8 @@ export interface LensStep<
|
|||||||
in out RSW = never,
|
in out RSW = never,
|
||||||
> {
|
> {
|
||||||
readonly [LensStepTypeId]: LensStepTypeId
|
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 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)
|
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 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>
|
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> {
|
private get access(): Effect.Effect<LensFrame<A, EW, RW>, ER, RR> {
|
||||||
let effect: Effect.Effect<unknown, unknown, unknown> = this.sourceGet
|
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)
|
for (const step of this.steps)
|
||||||
effect = step.transform(effect)
|
effect = step.access(effect as never) as Effect.Effect<LensFrame<unknown, unknown, unknown>, unknown, unknown>
|
||||||
return effect as Effect.Effect<A, ER, RR>
|
|
||||||
|
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> {
|
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>,
|
f: (a: A) => Effect.Effect<readonly [C, A], E1, R1>,
|
||||||
): Effect.Effect<C, ER | EW | E1, RR | RW | R1> {
|
): Effect.Effect<C, ER | EW | E1, RR | RW | R1> {
|
||||||
return this.withLock(Effect.flatMap(
|
return this.withLock(Effect.flatMap(
|
||||||
this.sourceGet,
|
this.access,
|
||||||
source => {
|
frame => Effect.flatMap(
|
||||||
const parents: unknown[] = []
|
f(frame.value),
|
||||||
let current: Effect.Effect<unknown, unknown, unknown> = Effect.succeed(source)
|
([c, next]) => Effect.as(frame.commit(Effect.succeed(next)), c),
|
||||||
|
),
|
||||||
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,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
))
|
))
|
||||||
},
|
|
||||||
)) as Effect.Effect<C, ER | EW | E1, RR | RW | R1>
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user