Skip to content

Instantly share code, notes, and snippets.

@timo-schmid
Created December 22, 2017 00:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save timo-schmid/803397672a32ce018208fd8062a805ab to your computer and use it in GitHub Desktop.
Save timo-schmid/803397672a32ce018208fd8062a805ab to your computer and use it in GitHub Desktop.
package btcboard.ui
import cats.Monad
import monocle.Lens
import scala.languageFeature.higherKinds
class Rx[A[_], T, O] private(t: T, lens: Lens[T, O], observers: T => A[Unit], monad: Monad[A]) {
def getT: T = t
def getO: O = lens.get(t)
def set(newValue: O): A[Rx[A, T, O]] = updateValue(lens.set(newValue)(t))
def bind(newObserver: O => A[Unit]): Rx[A, T, O] =
new Rx[A, T, O](t, lens, composeObservers(observers, newObserver, lens)(_), monad)
def zoom[Z](implicit newLens: monocle.Lens[O, Z]): Rx[A, T, Z] =
new Rx[A, T, Z](t, lens.composeLens(newLens), observers, monad)
private def updateValue(newValue: T): A[Rx[A, T, O]] =
monad.map[Unit, Rx[A, T, O]](observers(newValue))(_ => new Rx[A, T, O](newValue, lens, observers, monad))
private def composeObservers(observers: T => A[Unit], newObserver: O => A[Unit], lens: Lens[T, O])(t: T): A[Unit] =
monad.flatMap(observers(t)) { _ =>
monad.map(newObserver(lens.get(t)))(_ => ())
}
}
object Rx {
def apply[A[_], T](t: T)(implicit monad: Monad[A]): Rx[A, T, T] =
new Rx(t, Lens[T, T](identity)(t => _ => t), _ => monad.pure(()), monad)
def apply[A[_], T, O](t: T, lens: Lens[T, O])(implicit monad: Monad[A]): Rx[A, T, O] =
new Rx(t, lens, _ => monad.pure(()), monad)
def apply[A[_], T, O](t: T, lens: Lens[T, O], callbacks: T => A[Unit])(implicit monad: Monad[A]): Rx[A, T, O] =
new Rx(t, lens, callbacks, monad)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment