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

  1. package nova.monadic_sfx.util.reactive
  2. import cats.implicits._
  3. import monix.reactive.Observable
  4. import monix.reactive.ObservableLike
  5. object Reducer {
  6. /**
  7. * Creates a Reducer which yields a new State, as-well as an Observable of Effects
  8. * Effects are Actions which will be executed after the Action that caused them to occur.
  9. * This is accomplished by subscribing to the Effects Observable within the stores scan loop.
  10. *
  11. * CAUTION: There is currently a bug which causes the Effect-States to emit,
  12. * before the State of the action that caused the effects is emitted.
  13. * However, this only effects immediate emissions of the Effects Observable, delayed emissions should be fine.
  14. * @param f The Reducing Function returning the (Model, Effects) tuple.
  15. */
  16. def withEffects[F[_]: ObservableLike, A, M](
  17. f: (M, A) => (M, F[A])
  18. ): Reducer[A, M] = (s: M, a: A) => f(s, a).map(ObservableLike[F].apply)
  19. /**
  20. * Creates a reducer which just transforms the state, without additional effects.
  21. */
  22. def apply[A, M](f: (M, A) => M): Reducer[A, M] =
  23. (s: M, a: A) => f(s, a) -> Observable.empty
  24. /**
  25. * Creates a Reducer with an optional effect.
  26. */
  27. def withOptionalEffects[F[_]: ObservableLike, A, M](
  28. f: (M, A) => (M, Option[F[A]])
  29. ): Reducer[A, M] =
  30. (s: M, a: A) =>
  31. f(s, a).map(
  32. _.fold[Observable[A]](Observable.empty)(ObservableLike[F].apply)
  33. )
  34. }