@@ -6,13 +6,13 @@ import fs2.Async.Change
66import fs2 ._
77import fs2 .Stream ._
88import fs2 .async .immutable
9- import fs2 .util .Monad
9+ import fs2 .util .{ Monad , Functor }
1010
1111/**
1212 * A signal whose value may be set asynchronously. Provides continuous
1313 * and discrete streams for responding to changes to it's value.
1414 */
15- trait Signal [F [_],A ] extends immutable.Signal [F ,A ] {
15+ trait Signal [F [_], A ] extends immutable.Signal [F , A ] { self =>
1616
1717 /** Sets the value of this `Signal`. */
1818 def set (a : A ): F [Unit ]
@@ -24,13 +24,29 @@ trait Signal[F[_],A] extends immutable.Signal[F,A] {
2424 *
2525 * `F` returns the result of applying `op` to current value.
2626 */
27- def modify (f : A => A ): F [Change [A ]]
27+ def modify (f : A => A ): F [Change [A ]]
2828
2929 /**
3030 * Asynchronously refreshes the value of the signal,
3131 * keep the value of this `Signal` the same, but notify any listeners.
3232 */
3333 def refresh : F [Unit ]
34+
35+ /**
36+ * Returns an alternate view of this `Signal` where its elements are of type [[B ]],
37+ * given a function from `A` to `B`.
38+ */
39+ def imap [B ](f : A => B )(g : B => A )(implicit F : Functor [F ]): Signal [F , B ] =
40+ new Signal [F , B ] {
41+ def discrete : Stream [F , B ] = self.discrete.map(f)
42+ def continuous : Stream [F , B ] = self.continuous.map(f)
43+ def changes : Stream [F , Unit ] = self.changes
44+ def get : F [B ] = F .map(self.get)(f)
45+ def set (b : B ): F [Unit ] = self.set(g(b))
46+ def refresh : F [Unit ] = self.refresh
47+ def modify (bb : B => B ): F [Change [B ]] =
48+ F .map(self.modify(a => g(bb(f(a))))) { case Change (prev, now) => Change (f(prev), f(now)) }
49+ }
3450}
3551
3652object Signal {
0 commit comments