From 47073f2bf1605765be97c5d62256e3f500cbec26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Tue, 24 Mar 2026 23:05:22 +0100 Subject: [PATCH] Add fromRef --- packages/effect-fc/src/Lens.ts | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/packages/effect-fc/src/Lens.ts b/packages/effect-fc/src/Lens.ts index f755595..f347cd0 100644 --- a/packages/effect-fc/src/Lens.ts +++ b/packages/effect-fc/src/Lens.ts @@ -1,4 +1,4 @@ -import { Array, Chunk, Effect, Function, Pipeable, Predicate, Readable, Stream, Subscribable, type SubscriptionRef } from "effect" +import { Array, Chunk, Effect, Function, Pipeable, Predicate, Readable, type Ref, Stream, Subscribable, type SubscriptionRef } from "effect" import type { NoSuchElementException } from "effect/Cause" @@ -91,6 +91,28 @@ export const fromSubscriptionRef = ( ) => ref.modifyEffect(f), }) +/** + * Creates a `Lens` that proxies a `Ref`. + * + * Note: since `Ref` does not provide any kind of reactivity mechanism, the produced `Lens` will be non-reactive. + * This means its `changes` stream will only emit the current value once when evaluated and nothing else. + */ +export const fromRef = ( + ref: Ref.Ref +): Lens => make({ + get get() { return ref.get }, + get changes() { return Stream.unwrap(Effect.map(ref.get, Stream.make)) }, + modify: ( + f: (a: A) => Effect.Effect + ) => Effect.flatMap(ref.get, a => Effect.flatMap( + f(a), + ([b, next]) => Effect.flatMap( + ref.set(next), + () => Effect.succeed(b), + ), + )), +}) + /** * Flattens an effectful `Lens`. */