0.2.5 #43

Merged
Thilawyn merged 94 commits from next into master 2026-03-31 21:01:13 +02:00
2 changed files with 25 additions and 35 deletions
Showing only changes of commit 54b05ed8da - Show all commits

View File

@@ -1,4 +1,4 @@
import { Effect, Predicate, Stream, Subscribable, SubscriptionRef, type Types } from "effect" import { Effect, Pipeable, Predicate, Readable, Stream, Subscribable, SubscriptionRef } from "effect"
import * as Writable from "./Writable.js" import * as Writable from "./Writable.js"
@@ -6,62 +6,52 @@ export const LensTypeId: unique symbol = Symbol.for("@effect-fc/Lens/Lens")
export type LensTypeId = typeof LensTypeId export type LensTypeId = typeof LensTypeId
export interface Lens<in out A, ER = unknown, RR = unknown, EW = unknown, RW = unknown> export interface Lens<in out A, ER = unknown, RR = unknown, EW = unknown, RW = unknown>
extends Lens.Variance<A, ER, RR, EW, RW>, Subscribable.Subscribable<A, ER, RR>, Writable.Writable<A, EW, RW> {} extends LensPrototype, Subscribable.Subscribable<A, ER, RR>, Writable.Writable<A, EW, RW> {}
export declare namespace Lens {
export interface Variance<in out A, in out EGet, in out RGet, in out ESet, in out RSet> { export interface LensPrototype extends Pipeable.Pipeable {
readonly [LensTypeId]: { readonly [LensTypeId]: LensTypeId
readonly _A: Types.Invariant<A>
readonly _EG: Types.Invariant<EGet>
readonly _RG: Types.Invariant<RGet>
readonly _EW: Types.Invariant<ESet>
readonly _RW: Types.Invariant<RSet>
}
}
} }
export const LensPrototype: Writable.WritablePrototype = Object.freeze({ export const LensPrototype: LensPrototype = Object.freeze({
[LensTypeId]: LensTypeId, ...Pipeable.Prototype,
...Writable.WritablePrototype, ...Writable.WritablePrototype,
[Readable.TypeId]: Readable.TypeId,
[Subscribable.TypeId]: Subscribable.TypeId,
[LensTypeId]: LensTypeId,
} as const) } as const)
export const isLens = (u: unknown): u is Lens<unknown, unknown, unknown, unknown, unknown> => Predicate.hasProperty(u, LensTypeId) export const isLens = (u: unknown): u is Lens<unknown, unknown, unknown, unknown, unknown> => Predicate.hasProperty(u, LensTypeId)
export const make = <A, ER, RR, EW, RW>(options: {
/**
* Construct a `Lens` from explicit get/changes/set implementations.
*/
export const makeFromGetSet = <A, ER, RR, EW, RW>(options: {
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 set: (value: A) => Effect.Effect<void, EW, RW> readonly set: (value: A) => Effect.Effect<void, EW, RW>
}): Lens<A, ER, RR, EW, RW> => Object.setPrototypeOf({ }): Lens<A, ER, RR, EW, RW> => Object.setPrototypeOf({
[Subscribable.TypeId]: Subscribable.TypeId,
get: options.get, get: options.get,
changes: options.changes, changes: options.changes,
modify: <B>(f: (a: A) => readonly [B, A]) => Effect.flatMap(options.get, a => { modify: <B>(f: (a: A) => readonly [B, A]) => Effect.flatMap(options.get, a => {
const [b, next] = f(a) const [b, next] = f(a)
return Effect.map(options.set(next), () => b) return Effect.map(options.set(next), () => b)
}), }),
}, LensPrototype) as any }, LensPrototype)
/** /**
* Create a `Lens` that directly proxies an `effect` SubscriptionRef. * Creates a `Lens` that directly proxies a `SubscriptionRef`.
*/ */
export const makeFromSubscriptionRef = <A>(ref: SubscriptionRef.SubscriptionRef<A>): Lens<A, never, never, never, never> => export const fromSubscriptionRef = <A>(
makeFromGetSet({ ref: SubscriptionRef.SubscriptionRef<A>
get: ref, ): Lens<A, never, never, never, never> => make({
changes: ref.changes, get: ref.get,
set: (v: A) => SubscriptionRef.set(ref, v), changes: ref.changes,
}) set: (v: A) => SubscriptionRef.set(ref, v),
})
export const unwrap = <A, ER, RR, EW, RW, E1, R1>( export const unwrap = <A, ER, RR, EW, RW, E1, R1>(
effect: Effect.Effect<Lens<A, ER, RR, EW, RW>, E1, R1>, effect: Effect.Effect<Lens<A, ER, RR, EW, RW>, E1, R1>
): Lens<A, ER | E1, RR | R1, EW | E1, RW | R1> => makeFromGetSet({ ): Lens<A, ER | E1, RR | R1, EW | E1, RW | R1> => make({
get: Effect.flatMap(effect, p => p.get), get: Effect.flatMap(effect, p => p.get),
changes: Stream.unwrap(Effect.map(effect, p => p.changes)), changes: Stream.unwrap(Effect.map(effect, p => p.changes)),
set: (v: A) => Effect.flatMap(effect, p => p.modify(() => [undefined as void as any, v]) as any), set: (v: A) => Effect.flatMap(effect, p => p.modify(() => [undefined as void as any, v]) as any),
}) as any })

View File

@@ -25,14 +25,14 @@ export const isWritable = (u: unknown): u is Writable<unknown, unknown, unknown>
* Construct a `Writable` from a `modify` function. * Construct a `Writable` from a `modify` function.
*/ */
export const make = <A, E, R>( export const make = <A, E, R>(
modify: <B>(f: (a: A) => readonly [B, A]) => Effect.Effect<B, E, R>, modify: <B>(f: (a: A) => readonly [B, A]) => Effect.Effect<B, E, R>
): Writable<A, E, R> => Object.setPrototypeOf({ modify }, WritablePrototype) ): Writable<A, E, R> => Object.setPrototypeOf({ modify }, WritablePrototype)
/** /**
* Unwrap a `Writable` that is wrapped in an `Effect`. * Unwrap a `Writable` that is wrapped in an `Effect`.
*/ */
export const unwrap = <A, E, R, E1, R1>( export const unwrap = <A, E, R, E1, R1>(
effect: Effect.Effect<Writable<A, E, R>, E1, R1>, effect: Effect.Effect<Writable<A, E, R>, E1, R1>
): Writable<A, E | E1, R | R1> => make(<B>( ): Writable<A, E | E1, R | R1> => make(<B>(
f: (a: A) => readonly [B, A] f: (a: A) => readonly [B, A]
) => Effect.flatMap(effect, w => w.modify(f))) ) => Effect.flatMap(effect, w => w.modify(f)))