diff --git a/packages/effect-fc/src/Lens.ts b/packages/effect-fc/src/Lens.ts index 3aa73f1..3ecc1dc 100644 --- a/packages/effect-fc/src/Lens.ts +++ b/packages/effect-fc/src/Lens.ts @@ -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" @@ -6,62 +6,52 @@ export const LensTypeId: unique symbol = Symbol.for("@effect-fc/Lens/Lens") export type LensTypeId = typeof LensTypeId export interface Lens - extends Lens.Variance, Subscribable.Subscribable, Writable.Writable {} +extends LensPrototype, Subscribable.Subscribable, Writable.Writable {} -export declare namespace Lens { - export interface Variance { - readonly [LensTypeId]: { - readonly _A: Types.Invariant - readonly _EG: Types.Invariant - readonly _RG: Types.Invariant - readonly _EW: Types.Invariant - readonly _RW: Types.Invariant - } - } + +export interface LensPrototype extends Pipeable.Pipeable { + readonly [LensTypeId]: LensTypeId } -export const LensPrototype: Writable.WritablePrototype = Object.freeze({ - [LensTypeId]: LensTypeId, +export const LensPrototype: LensPrototype = Object.freeze({ + ...Pipeable.Prototype, ...Writable.WritablePrototype, + [Readable.TypeId]: Readable.TypeId, + [Subscribable.TypeId]: Subscribable.TypeId, + [LensTypeId]: LensTypeId, } as const) export const isLens = (u: unknown): u is Lens => Predicate.hasProperty(u, LensTypeId) - -/** - * Construct a `Lens` from explicit get/changes/set implementations. - */ -export const makeFromGetSet = (options: { +export const make = (options: { readonly get: Effect.Effect readonly changes: Stream.Stream readonly set: (value: A) => Effect.Effect }): Lens => Object.setPrototypeOf({ - [Subscribable.TypeId]: Subscribable.TypeId, get: options.get, changes: options.changes, modify: (f: (a: A) => readonly [B, A]) => Effect.flatMap(options.get, a => { const [b, next] = f(a) 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 = (ref: SubscriptionRef.SubscriptionRef): Lens => - makeFromGetSet({ - get: ref, - changes: ref.changes, - set: (v: A) => SubscriptionRef.set(ref, v), - }) - +export const fromSubscriptionRef = ( + ref: SubscriptionRef.SubscriptionRef +): Lens => make({ + get: ref.get, + changes: ref.changes, + set: (v: A) => SubscriptionRef.set(ref, v), +}) export const unwrap = ( - effect: Effect.Effect, E1, R1>, -): Lens => makeFromGetSet({ + effect: Effect.Effect, E1, R1> +): Lens => make({ get: Effect.flatMap(effect, p => p.get), 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), -}) as any +}) diff --git a/packages/effect-fc/src/Writable.ts b/packages/effect-fc/src/Writable.ts index 071ad95..b415702 100644 --- a/packages/effect-fc/src/Writable.ts +++ b/packages/effect-fc/src/Writable.ts @@ -25,14 +25,14 @@ export const isWritable = (u: unknown): u is Writable * Construct a `Writable` from a `modify` function. */ export const make = ( - modify: (f: (a: A) => readonly [B, A]) => Effect.Effect, + modify: (f: (a: A) => readonly [B, A]) => Effect.Effect ): Writable => Object.setPrototypeOf({ modify }, WritablePrototype) /** * Unwrap a `Writable` that is wrapped in an `Effect`. */ export const unwrap = ( - effect: Effect.Effect, E1, R1>, + effect: Effect.Effect, E1, R1> ): Writable => make(( f: (a: A) => readonly [B, A] ) => Effect.flatMap(effect, w => w.modify(f)))