You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
39 lines
1.4 KiB
39 lines
1.4 KiB
package nova.monadic_sfx.util.reactive.store
|
|
|
|
import cats.implicits._
|
|
import monix.reactive.Observable
|
|
import monix.reactive.ObservableLike
|
|
|
|
object Reducer {
|
|
|
|
/**
|
|
* Creates a Reducer which yields a new State, as-well as an Observable of Effects
|
|
* Effects are Actions which will be executed after the Action that caused them to occur.
|
|
* This is accomplished by subscribing to the Effects Observable within the stores scan loop.
|
|
*
|
|
* CAUTION: There is currently a bug which causes the Effect-States to emit,
|
|
* before the State of the action that caused the effects is emitted.
|
|
* However, this only effects immediate emissions of the Effects Observable, delayed emissions should be fine.
|
|
* @param f The Reducing Function returning the (Model, Effects) tuple.
|
|
*/
|
|
def withEffects[F[_]: ObservableLike, A, M](
|
|
f: (M, A) => (M, F[A])
|
|
): Reducer[A, M] = (s: M, a: A) => f(s, a).map(ObservableLike[F].apply)
|
|
|
|
/**
|
|
* Creates a reducer which just transforms the state, without additional effects.
|
|
*/
|
|
def apply[A, M](f: (M, A) => M): Reducer[A, M] =
|
|
(s: M, a: A) => f(s, a) -> Observable.empty
|
|
|
|
/**
|
|
* Creates a Reducer with an optional effect.
|
|
*/
|
|
def withOptionalEffects[F[_]: ObservableLike, A, M](
|
|
f: (M, A) => (M, Option[F[A]])
|
|
): Reducer[A, M] =
|
|
(s: M, a: A) =>
|
|
f(s, a).map(
|
|
_.fold[Observable[A]](Observable.empty)(ObservableLike[F].apply)
|
|
)
|
|
}
|