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`.
*/