Skip to content

Instantly share code, notes, and snippets.

@kaisellgren
Last active January 7, 2016 03:03
Show Gist options
  • Select an option

  • Save kaisellgren/11393718 to your computer and use it in GitHub Desktop.

Select an option

Save kaisellgren/11393718 to your computer and use it in GitHub Desktop.

Revisions

  1. kaisellgren revised this gist Apr 29, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion foldpImmutable.scala
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    // How do I implement foldp[A, B] for SignalImmutable[A] (or SignalImmutableStateMonad[A]) ?
    // How do I implement foldp[A, B] for SignalImmutable[A] (or SignalSM[A]) ?
    // TODO: Does not work at all!

    def foldpImmutable[A, B](source: SignalImmutable[A], initial: B)(predicate: (B, A) => B): SignalImmutable[B] = {
  2. kaisellgren revised this gist Apr 29, 2014. 3 changed files with 11 additions and 7 deletions.
    6 changes: 3 additions & 3 deletions Signal.scala
    Original file line number Diff line number Diff line change
    @@ -1,10 +1,10 @@
    // This first Signal[A] impl. uses STM (Ref — transactional references).

    class Signal[A](initial: A) {
    type Listener = Function[A, Unit]
    type SignalListener = Function[A, Unit]

    val value = Ref(initial)
    val listeners = Ref(Seq[Listener]())
    val listeners = Ref(Seq[SignalListener]())

    def set(newValue: A): Unit = {
    // Atomically change the value within a transaction, blocks the thread, but a not an issue since it's a simple operation.
    @@ -20,7 +20,7 @@ class Signal[A](initial: A) {
    }

    /** Sets a new listener. */
    def listen(listener: Listener): Unit = atomic { implicit txn =>
    def listen(listener: SignalListener): Unit = atomic { implicit txn =>
    listeners() = listeners() :+ listener
    }
    }
    6 changes: 4 additions & 2 deletions SignalImmutable.scala
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,8 @@
    // An immutable version called SignalImmutable[A]. Based on the concept of state transformations.

    case class SignalImmutable[A](value: A, listeners: Seq[Function[A, Unit]] = Seq())
    package object Foo { type SignalListener = Function[A, Unit] }

    case class SignalImmutable[A](value: A, listeners: Seq[SignalListener] = Seq())

    object SignalImmutable {
    def set[A](newValue: A)(signal: SignalImmutable[A]): SignalImmutable[A] = {
    @@ -10,7 +12,7 @@ object SignalImmutable {

    def get[A](signal: SignalImmutable[A]): A = signal.value

    def listen[A](listener: Function[A, Unit])(signal: SignalImmutable[A]): SignalImmutable[A] = {
    def listen[A](listener: SignalListener)(signal: SignalImmutable[A]): SignalImmutable[A] = {
    signal.copy(listeners = signal.listeners :+ listener)
    }
    }
    6 changes: 4 additions & 2 deletions SignalImmutableStateMonad.scala
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,8 @@
    // This version is immutable and uses state monads.

    case class SignalSM[A](value: A, listeners: Seq[Function[A, Unit]] = Seq())
    package object Foo { type SignalListener = Function[A, Unit] }

    case class SignalSM[A](value: A, listeners: Seq[SignalListener] = Seq())

    object SignalSM {
    def set[A](newValue: A): State[SignalSM[A], Unit] = State(signal => {
    @@ -10,7 +12,7 @@ object SignalSM {

    def get[A]: State[SignalSM[A], A] = State(signal => (signal, signal.value))

    def listen[A](listener: Function[A, Unit]): State[SignalSM[A], Unit] = State(signal => {
    def listen[A](listener: SignalListener): State[SignalSM[A], Unit] = State(signal => {
    (signal.copy(listeners = signal.listeners :+ listener), ())
    })
    }
  3. kaisellgren revised this gist Apr 29, 2014. 1 changed file with 9 additions and 9 deletions.
    18 changes: 9 additions & 9 deletions SignalImmutableStateMonad.scala
    Original file line number Diff line number Diff line change
    @@ -1,27 +1,27 @@
    // This version is immutable and uses state monads.

    case class SignalImmutableStateMonad[A](value: A, listeners: Seq[Function[A, Unit]] = Seq())
    case class SignalSM[A](value: A, listeners: Seq[Function[A, Unit]] = Seq())

    object SignalImmutableStateMonad {
    def set[A](newValue: A): State[SignalImmutableStateMonad[A], Unit] = State(signal => {
    object SignalSM {
    def set[A](newValue: A): State[SignalSM[A], Unit] = State(signal => {
    signal.listeners.foreach(_(newValue))
    (signal.copy(value = newValue), ())
    })

    def get[A]: State[SignalImmutableStateMonad[A], A] = State(signal => (signal, signal.value))
    def get[A]: State[SignalSM[A], A] = State(signal => (signal, signal.value))

    def listen[A](listener: Function[A, Unit]): State[SignalImmutableStateMonad[A], Unit] = State(signal => {
    def listen[A](listener: Function[A, Unit]): State[SignalSM[A], Unit] = State(signal => {
    (signal.copy(listeners = signal.listeners :+ listener), ())
    })
    }

    object Foo extends App {
    val state = for {
    _ <- SignalImmutableStateMonad.set(10)
    _ <- SignalImmutableStateMonad.listen({ value: Int => println(s"Here it is: $value")})
    _ <- SignalImmutableStateMonad.set(20)
    _ <- SignalSM.set(10)
    _ <- SignalSM.listen({ value: Int => println(s"Here it is: $value")})
    _ <- SignalSM.set(20)
    s <- State.get
    } yield s

    state.exec(SignalImmutableStateMonad(5))
    state.exec(SignalSM(5))
    }
  4. kaisellgren revised this gist Apr 29, 2014. 2 changed files with 28 additions and 1 deletion.
    27 changes: 27 additions & 0 deletions SignalImmutableStateMonad.scala
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,27 @@
    // This version is immutable and uses state monads.

    case class SignalImmutableStateMonad[A](value: A, listeners: Seq[Function[A, Unit]] = Seq())

    object SignalImmutableStateMonad {
    def set[A](newValue: A): State[SignalImmutableStateMonad[A], Unit] = State(signal => {
    signal.listeners.foreach(_(newValue))
    (signal.copy(value = newValue), ())
    })

    def get[A]: State[SignalImmutableStateMonad[A], A] = State(signal => (signal, signal.value))

    def listen[A](listener: Function[A, Unit]): State[SignalImmutableStateMonad[A], Unit] = State(signal => {
    (signal.copy(listeners = signal.listeners :+ listener), ())
    })
    }

    object Foo extends App {
    val state = for {
    _ <- SignalImmutableStateMonad.set(10)
    _ <- SignalImmutableStateMonad.listen({ value: Int => println(s"Here it is: $value")})
    _ <- SignalImmutableStateMonad.set(20)
    s <- State.get
    } yield s

    state.exec(SignalImmutableStateMonad(5))
    }
    2 changes: 1 addition & 1 deletion foldpImmutable.scala
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    // How do I implement foldp[A, B] for ImmutableSignal[A] ?
    // How do I implement foldp[A, B] for SignalImmutable[A] (or SignalImmutableStateMonad[A]) ?
    // TODO: Does not work at all!

    def foldpImmutable[A, B](source: SignalImmutable[A], initial: B)(predicate: (B, A) => B): SignalImmutable[B] = {
  5. kaisellgren revised this gist Apr 29, 2014. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions foldpImmutable.scala
    Original file line number Diff line number Diff line change
    @@ -5,6 +5,7 @@ def foldpImmutable[A, B](source: SignalImmutable[A], initial: B)(predicate: (B,
    val result = SignalImmutable(initial)

    SignalImmutable.listen({ ev: A =>
    // Great, so how do I actually update ´result´?
    SignalImmutable.set(predicate(SignalImmutable.get(result), ev))
    })(source)

    @@ -15,6 +16,7 @@ object Foo extends App {
    val clicks = SignalImmutable(0)
    val totalClicks = foldpImmutable(clicks, 0) {(previous: Int, current: Int) => previous + 1}

    // This creates a new SignalImmutable, all hell breaks loose.
    SignalImmutable.set(0)(clicks)

    println(totalClicks.value)
  6. kaisellgren revised this gist Apr 29, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion foldp-stm.scala
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,6 @@
    // foldp[A, B] impl. for Signal[A], i.e. the STM -version.

    // foldp := (Signal<A>, (B, A) => B, B) => Signal<B>
    // This function is defined as: foldp := (Signal<A>, (B, A) => B, B) => Signal<B>

    def foldp[A, B](source: Signal[A], initial: B)(predicate: (B, A) => B): Signal[B] = {
    val result = new Signal(initial)
  7. kaisellgren revised this gist Apr 29, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion SignalImmutable.scala
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    // An immutable version of Signal[A]. Based on the concept of state transformations.
    // An immutable version called SignalImmutable[A]. Based on the concept of state transformations.

    case class SignalImmutable[A](value: A, listeners: Seq[Function[A, Unit]] = Seq())

  8. kaisellgren revised this gist Apr 29, 2014. 4 changed files with 6 additions and 2 deletions.
    2 changes: 2 additions & 0 deletions Signal.scala
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,5 @@
    // This first Signal[A] impl. uses STM (Ref — transactional references).

    class Signal[A](initial: A) {
    type Listener = Function[A, Unit]

    2 changes: 1 addition & 1 deletion SignalImmutable.scala
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    // An immutable version of Signal[A].
    // An immutable version of Signal[A]. Based on the concept of state transformations.

    case class SignalImmutable[A](value: A, listeners: Seq[Function[A, Unit]] = Seq())

    2 changes: 2 additions & 0 deletions foldp-stm.scala
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,5 @@
    // foldp[A, B] impl. for Signal[A], i.e. the STM -version.

    // foldp := (Signal<A>, (B, A) => B, B) => Signal<B>

    def foldp[A, B](source: Signal[A], initial: B)(predicate: (B, A) => B): Signal[B] = {
    2 changes: 1 addition & 1 deletion foldpImmutable.scala
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    // How do I implement this?
    // How do I implement foldp[A, B] for ImmutableSignal[A] ?
    // TODO: Does not work at all!

    def foldpImmutable[A, B](source: SignalImmutable[A], initial: B)(predicate: (B, A) => B): SignalImmutable[B] = {
  9. kaisellgren revised this gist Apr 29, 2014. 2 changed files with 2 additions and 2 deletions.
    2 changes: 1 addition & 1 deletion foldp-stm.scala
    Original file line number Diff line number Diff line change
    @@ -4,7 +4,7 @@ def foldp[A, B](source: Signal[A], initial: B)(predicate: (B, A) => B): Signal[B
    val result = new Signal(initial)

    source.listen({ ev: A =>
    result.set(predicate(result.get, source.get))
    result.set(predicate(result.get, ev))
    })

    result
    2 changes: 1 addition & 1 deletion foldpImmutable.scala
    Original file line number Diff line number Diff line change
    @@ -5,7 +5,7 @@ def foldpImmutable[A, B](source: SignalImmutable[A], initial: B)(predicate: (B,
    val result = SignalImmutable(initial)

    SignalImmutable.listen({ ev: A =>
    SignalImmutable.set(predicate(SignalImmutable.get(result), source.value))
    SignalImmutable.set(predicate(SignalImmutable.get(result), ev))
    })(source)

    result
  10. kaisellgren renamed this gist Apr 29, 2014. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  11. kaisellgren revised this gist Apr 29, 2014. 4 changed files with 49 additions and 7 deletions.
    11 changes: 4 additions & 7 deletions Signal.scala
    Original file line number Diff line number Diff line change
    @@ -1,16 +1,12 @@
    // Haskell Signal and foldp implementation.

    // foldp := (Signal<A>, (B, A) => B, B) => Signal<B>

    class Signal[A](initial: A) {
    type Listener = Function[A, Unit]

    val value = Ref(initial)
    val listeners = Ref(Seq[Listener]())

    def set(newValue: A): Unit = {
    // Atomically change the value, blocks the thread, but a not an issue since it's a simple operation.
    // Finally return the current state/set of listeners.
    // Atomically change the value within a transaction, blocks the thread, but a not an issue since it's a simple operation.
    // Finally return the current state/set of listeners and calls them.
    atomic { implicit txn =>
    value() = newValue
    listeners()
    @@ -21,6 +17,7 @@ class Signal[A](initial: A) {
    value()
    }

    /** Sets a new listener. */
    def listen(listener: Listener): Unit = atomic { implicit txn =>
    listeners() = listeners() :+ listener
    }
    @@ -30,7 +27,7 @@ object Foo extends App {
    val slot = new Signal(0)

    slot.listen({ value =>
    println(value) // hooray!
    println(value) // Hooray! it prints 5!
    })

    slot.set(5)
    3 changes: 3 additions & 0 deletions SignalImmutable.scala
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,5 @@
    // An immutable version of Signal[A].

    case class SignalImmutable[A](value: A, listeners: Seq[Function[A, Unit]] = Seq())

    object SignalImmutable {
    @@ -14,6 +16,7 @@ object SignalImmutable {
    }

    object Foo extends App {
    // New instances after every state change. Ugly, yes.
    val sig = SignalImmutable(1)
    val sig2 = SignalImmutable.listen({v: Int => println(v)})(sig)
    val sig3 = SignalImmutable.set(5)(sig2)
    21 changes: 21 additions & 0 deletions foldp-immutable.scala
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,21 @@
    // How do I implement this?
    // TODO: Does not work at all!

    def foldpImmutable[A, B](source: SignalImmutable[A], initial: B)(predicate: (B, A) => B): SignalImmutable[B] = {
    val result = SignalImmutable(initial)

    SignalImmutable.listen({ ev: A =>
    SignalImmutable.set(predicate(SignalImmutable.get(result), source.value))
    })(source)

    result
    }

    object Foo extends App {
    val clicks = SignalImmutable(0)
    val totalClicks = foldpImmutable(clicks, 0) {(previous: Int, current: Int) => previous + 1}

    SignalImmutable.set(0)(clicks)

    println(totalClicks.value)
    }
    21 changes: 21 additions & 0 deletions foldp-stm.scala
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,21 @@
    // foldp := (Signal<A>, (B, A) => B, B) => Signal<B>

    def foldp[A, B](source: Signal[A], initial: B)(predicate: (B, A) => B): Signal[B] = {
    val result = new Signal(initial)

    source.listen({ ev: A =>
    result.set(predicate(result.get, source.get))
    })

    result
    }

    object Foo extends App {
    val clicks = new Signal(0)
    val totalClicks = foldp(clicks, 0) { (previous: Int, current: Int) => previous + 1}

    clicks.set(0)
    clicks.set(0)

    println(totalClicks.get) // 2!
    }
  12. kaisellgren revised this gist Apr 29, 2014. 1 changed file with 3 additions and 2 deletions.
    5 changes: 3 additions & 2 deletions Signal.scala
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,8 @@
    // Haskell Signal foldp implementation.
    // Haskell Signal and foldp implementation.

    // foldp := (Signal<A>, (B, A) => B, B) => Signal<B>

    class Signal[A](initial: A) {
    // Listener :: A => Unit or however you annotate it in Haskell..
    type Listener = Function[A, Unit]

    val value = Ref(initial)
  13. kaisellgren revised this gist Apr 29, 2014. 1 changed file with 20 additions and 0 deletions.
    20 changes: 20 additions & 0 deletions SignalImmutable.scala
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,20 @@
    case class SignalImmutable[A](value: A, listeners: Seq[Function[A, Unit]] = Seq())

    object SignalImmutable {
    def set[A](newValue: A)(signal: SignalImmutable[A]): SignalImmutable[A] = {
    signal.listeners.foreach(_(newValue))
    signal.copy(value = newValue)
    }

    def get[A](signal: SignalImmutable[A]): A = signal.value

    def listen[A](listener: Function[A, Unit])(signal: SignalImmutable[A]): SignalImmutable[A] = {
    signal.copy(listeners = signal.listeners :+ listener)
    }
    }

    object Foo extends App {
    val sig = SignalImmutable(1)
    val sig2 = SignalImmutable.listen({v: Int => println(v)})(sig)
    val sig3 = SignalImmutable.set(5)(sig2)
    }
  14. kaisellgren created this gist Apr 29, 2014.
    36 changes: 36 additions & 0 deletions Signal.scala
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,36 @@
    // Haskell Signal foldp implementation.

    class Signal[A](initial: A) {
    // Listener :: A => Unit or however you annotate it in Haskell..
    type Listener = Function[A, Unit]

    val value = Ref(initial)
    val listeners = Ref(Seq[Listener]())

    def set(newValue: A): Unit = {
    // Atomically change the value, blocks the thread, but a not an issue since it's a simple operation.
    // Finally return the current state/set of listeners.
    atomic { implicit txn =>
    value() = newValue
    listeners()
    }.foreach(_(newValue))
    }

    def get: A = atomic { implicit txn =>
    value()
    }

    def listen(listener: Listener): Unit = atomic { implicit txn =>
    listeners() = listeners() :+ listener
    }
    }

    object Foo extends App {
    val slot = new Signal(0)

    slot.listen({ value =>
    println(value) // hooray!
    })

    slot.set(5)
    }