0.2.0 #5

Merged
Thilawyn merged 59 commits from next into master 2026-05-30 06:10:54 +02:00
Showing only changes of commit a65f139858 - Show all commits
+33 -36
View File
@@ -35,18 +35,24 @@ extends Lens<A, ER, EW, RR, RW> {
readonly [LensWithInternalsTypeId]: LensWithInternalsTypeId readonly [LensWithInternalsTypeId]: LensWithInternalsTypeId
readonly update: (a: A) => Effect.Effect<void, EW, RW> readonly update: (a: A) => Effect.Effect<void, EW, RW>
readonly semaphore: Effect.Semaphore readonly withLock: <A1, E1, R1>(self: Effect.Effect<A1, E1, R1>) => Effect.Effect<A1, E1, R1>
} }
export const isLensWithInternals = (u: unknown): u is LensWithInternals<unknown, unknown, unknown, unknown, unknown> => Predicate.hasProperty(u, LensWithInternalsTypeId) export const isLensWithInternals = (u: unknown): u is LensWithInternals<unknown, unknown, unknown, unknown, unknown> => Predicate.hasProperty(u, LensWithInternalsTypeId)
export const asLensWithInternals = <A, ER, EW, RR, RW>(
lens: Lens<A, ER, EW, RR, RW>
): Effect.Effect<LensWithInternals<A, ER, EW, RR, RW>, never, never> => isLensWithInternals(lens)
? Effect.succeed(lens as LensWithInternals<A, ER, EW, RR, RW>)
: Effect.die("Not a 'LensWithInternals'.")
export declare namespace LensImpl { export declare namespace LensImpl {
export interface Source<in out A, in out ER = never, in out EW = never, in out RR = never, in out RW = never> { export interface Source<in out A, in out ER = never, in out EW = never, in out RR = never, in out RW = never> {
readonly get: Effect.Effect<A, ER, RR>, readonly get: Effect.Effect<A, ER, RR>,
readonly changes: Stream.Stream<A, ER, RR>, readonly changes: Stream.Stream<A, ER, RR>,
readonly update: (a: A) => Effect.Effect<void, EW, RW>, readonly update: (a: A) => Effect.Effect<void, EW, RW>,
readonly semaphore: Effect.Semaphore, readonly withLock: <A1, E1, R1>(self: Effect.Effect<A1, E1, R1>) => Effect.Effect<A1, E1, R1>,
} }
} }
@@ -60,7 +66,7 @@ extends Pipeable.Class() implements LensWithInternals<A, ER, EW, RR, RW> {
readonly get: Effect.Effect<A, ER, RR> readonly get: Effect.Effect<A, ER, RR>
readonly changes: Stream.Stream<A, ER, RR> readonly changes: Stream.Stream<A, ER, RR>
readonly update: (a: A) => Effect.Effect<void, EW, RW> readonly update: (a: A) => Effect.Effect<void, EW, RW>
readonly semaphore: Effect.Semaphore readonly withLock: <A1, E1, R1>(self: Effect.Effect<A1, E1, R1>) => Effect.Effect<A1, E1, R1>
constructor( constructor(
source: LensImpl.Source<A, ER, EW, RR, RW> source: LensImpl.Source<A, ER, EW, RR, RW>
@@ -70,19 +76,20 @@ extends Pipeable.Class() implements LensWithInternals<A, ER, EW, RR, RW> {
this.get = source.get this.get = source.get
this.changes = source.changes this.changes = source.changes
this.update = source.update this.update = source.update
this.semaphore = source.semaphore this.withLock = source.withLock
} }
modifyEffect<B, E1 = never, R1 = never>( modifyEffect = modifyEffect
f: (a: A) => Effect.Effect<readonly [B, A], E1, R1> }
) {
return this.semaphore.withPermits(1)( function modifyEffect<A, B, ER = never, EW = never, E1 = never, RR = never, RW = never, R1 = never>(
Effect.flatMap( this: LensWithInternals<A, ER, EW, RR, RW>,
f: (a: A) => Effect.Effect<readonly [B, A], E1, R1>,
): Effect.Effect<B, ER | EW | E1, RR | RW | R1> {
return this.withLock(Effect.flatMap(
this.get, this.get,
a => Effect.flatMap(f(a), ([b, next]) => Effect.as(this.update(next), b), a => Effect.flatMap(f(a), ([b, next]) => Effect.as(this.update(next), b),
)) )))
)
}
} }
/** /**
@@ -109,18 +116,9 @@ extends Pipeable.Class() implements LensWithInternals<A, ER, EW, RR, RW> {
get get() { return this.source.get } get get() { return this.source.get }
get changes() { return this.source.changes } get changes() { return this.source.changes }
get update() { return this.source.update } get update() { return this.source.update }
get semaphore() { return this.source.semaphore } get withLock() { return this.source.withLock }
modifyEffect<B, E1 = never, R1 = never>( modifyEffect = modifyEffect
f: (a: A) => Effect.Effect<readonly [B, A], E1, R1>
) {
return this.semaphore.withPermits(1)(
Effect.flatMap(
this.get,
a => Effect.flatMap(f(a), ([b, next]) => Effect.as(this.update(next), b),
))
)
}
} }
/** /**
@@ -164,18 +162,9 @@ extends Pipeable.Class() implements LensWithInternals<A, never, never, never, ne
PubSub.publish(this.ref.pubsub, a), PubSub.publish(this.ref.pubsub, a),
) )
} }
get semaphore() { return this.ref.semaphore } get withLock() { return this.ref.semaphore.withPermits(1) }
modifyEffect<B, E1 = never, R1 = never>( modifyEffect = modifyEffect
f: (a: A) => Effect.Effect<readonly [B, A], E1, R1>
) {
return this.semaphore.withPermits(1)(
Effect.flatMap(
this.get,
a => Effect.flatMap(f(a), ([b, next]) => Effect.as(this.update(next), b),
))
)
}
} }
/** /**
@@ -211,8 +200,16 @@ export const unwrap = <A, ER, EW, RR, RW, E1, R1>(
): Lens<A, ER | E1, EW | E1, RR | R1, RW | R1> => make({ ): Lens<A, ER | E1, EW | E1, RR | R1, RW | R1> => make({
get: Effect.flatMap(effect, l => l.get), get: Effect.flatMap(effect, l => l.get),
changes: Stream.unwrap(Effect.map(effect, l => l.changes)), changes: Stream.unwrap(Effect.map(effect, l => l.changes)),
update: a => Effect.flatMap(effect, l => (l as LensWithInternals<A, ER, EW, RR, RW>).update(a)) update: a => Effect.flatMap(
effect,
l => Effect.flatMap(asLensWithInternals(l), l => l.update(a))
),
withLock: <A2, E2, R2>(
effect2: Effect.Effect<A2, E2, R2>
): Effect.Effect<A2, E1 | E2, R1 | R2> => Effect.flatMap(
effect,
l => Effect.flatMap(asLensWithInternals(l), l2 => l2.withLock(effect2)),
),
}) })
/** /**