@@ -28,8 +28,11 @@ import cats.effect.std.MapRef
28
28
import cats .effect .syntax .all ._
29
29
import cats .syntax .all ._
30
30
import cats .{Applicative , Functor , Invariant , Monad }
31
-
31
+ import cats . arrow . FunctionK
32
32
import scala .collection .immutable .LongMap
33
+ import fs2 .concurrent .SignallingRef .TransformedSignallingRef
34
+ import fs2 .concurrent .Signal .TransformedSignal
35
+ import cats .data .State
33
36
34
37
/** Pure holder of a single value of type `A` that can be read in the effect `F`. */
35
38
trait Signal [F [_], A ] { outer =>
@@ -135,6 +138,11 @@ trait Signal[F[_], A] { outer =>
135
138
*/
136
139
def waitUntil (p : A => Boolean )(implicit F : Concurrent [F ]): F [Unit ] =
137
140
discrete.forall(a => ! p(a)).compile.drain
141
+
142
+ def mapK [G [_]](
143
+ f : FunctionK [F , G ]
144
+ ): Signal [G , A ] =
145
+ new TransformedSignal (this , f)
138
146
}
139
147
140
148
object Signal extends SignalInstances {
@@ -162,6 +170,16 @@ object Signal extends SignalInstances {
162
170
def get : F [B ] = Functor [F ].map(fa.get)(f)
163
171
}
164
172
173
+ final private class TransformedSignal [F [_], G [_], A ](
174
+ underlying : Signal [F , A ],
175
+ trans : FunctionK [F , G ]
176
+ ) extends Signal [G , A ] {
177
+ override def get : G [A ] = trans(underlying.get)
178
+ override def discrete : Stream [G , A ] = underlying.discrete.translate(trans)
179
+ override def continuous : Stream [G , A ] = underlying.continuous.translate(trans)
180
+ override def changes (implicit eqA : Eq [A ]): Signal [G , A ] = underlying.changes.mapK(trans)
181
+ }
182
+
165
183
implicit class SignalOps [F [_], A ](val self : Signal [F , A ]) extends AnyVal {
166
184
167
185
/** Converts this signal to signal of `B` by applying `f`.
@@ -196,7 +214,12 @@ object Signal extends SignalInstances {
196
214
* function, in the presence of `discrete`, can return `false` and
197
215
* need looping even without any other writers.
198
216
*/
199
- abstract class SignallingRef [F [_], A ] extends Ref [F , A ] with Signal [F , A ]
217
+ abstract class SignallingRef [F [_], A ] extends Ref [F , A ] with Signal [F , A ] {
218
+ def mapK [G [_]](
219
+ f : FunctionK [F , G ]
220
+ )(implicit G : Functor [G ], dummy : DummyImplicit ): SignallingRef [G , A ] =
221
+ new TransformedSignallingRef (this , f)
222
+ }
200
223
201
224
object SignallingRef {
202
225
@@ -222,6 +245,7 @@ object SignallingRef {
222
245
*
223
246
* @see [[of ]]
224
247
*/
248
+
225
249
def apply [F [_]]: PartiallyApplied [F ] = new PartiallyApplied [F ]
226
250
227
251
/** Alias for `of`. */
@@ -341,7 +365,31 @@ object SignallingRef {
341
365
ref : SignallingRef [F , A ]
342
366
)(get : A => B , set : A => B => A )(implicit F : Functor [F ]): SignallingRef [F , B ] =
343
367
new LensSignallingRef (ref)(get, set)
344
-
368
+ final private class TransformedSignallingRef [F [_], G [_], A ](
369
+ underlying : SignallingRef [F , A ],
370
+ trans : FunctionK [F , G ]
371
+ )(implicit G : Functor [G ])
372
+ extends SignallingRef [G , A ] {
373
+
374
+ // --- Ref methods: these are lifted using trans, just like in TransformedRef2
375
+ override def get : G [A ] = trans(underlying.get)
376
+ override def set (a : A ): G [Unit ] = trans(underlying.set(a))
377
+ override def getAndSet (a : A ): G [A ] = trans(underlying.getAndSet(a))
378
+ override def tryUpdate (f : A => A ): G [Boolean ] = trans(underlying.tryUpdate(f))
379
+ override def tryModify [B ](f : A => (A , B )): G [Option [B ]] = trans(underlying.tryModify(f))
380
+ override def update (f : A => A ): G [Unit ] = trans(underlying.update(f))
381
+ override def modify [B ](f : A => (A , B )): G [B ] = trans(underlying.modify(f))
382
+ override def tryModifyState [B ](state : State [A , B ]): G [Option [B ]] =
383
+ trans(underlying.tryModifyState(state))
384
+ override def modifyState [B ](state : State [A , B ]): G [B ] = trans(underlying.modifyState(state))
385
+ override def access : G [(A , A => G [Boolean ])] =
386
+ G .compose[(A , * )].compose[A => * ].map(trans(underlying.access))(trans(_))
387
+
388
+ // --- Signal-specific methods
389
+ override def discrete : Stream [G , A ] = underlying.discrete.translate(trans)
390
+ override def continuous : Stream [G , A ] = underlying.continuous.translate(trans)
391
+ override def changes (implicit eqA : Eq [A ]): Signal [G , A ] = underlying.changes.mapK(trans)
392
+ }
345
393
private final class LensSignallingRef [F [_], A , B ](underlying : SignallingRef [F , A ])(
346
394
lensGet : A => B ,
347
395
lensSet : A => B => A
0 commit comments