Skip to content
This repository was archived by the owner on Feb 14, 2021. It is now read-only.

Adding docs per push-pull paper #24

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 7 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,32 @@

[![Gitter](https://badges.gitter.im/scalaz/scalaz-reactive.svg)](https://gitter.im/scalaz/scalaz-reactive?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)


# Goal
## Goal

A high-performance, purely-functional library for reactive programming based on efficient incremental computation.

# Introduction
## Introduction

This library aims at faithfully implementing Functional Reactive Programming as defined in [2].
The term _Reactive programming_
is often used to describe composing streams of discrete events. Functional reactive programming (FRP) is about
composing dynamic values changing in continuous time and reacting to discrete events.

# Core concepts
## Core concepts

`Behaviour[A](value: Reactive[TimeFun[A]])` - value chaninging over time.
`Behaviour[A](value: Reactive[TimeFun[A]])` - value changing over time.

`Event[+A](value: Future[Reactive[A]])` - stream of (Time, a) pairs.

`Reactive[+A](head: A, tail: Event[A])` - reactive value.

`Sink[A, B](f: A => IO[Void, Unit])` - consumer of reactive values.


# Example
## Example

This project is just starting, so the working example is quite simple:

```
```scala
case class Tick(name: String)

def ticks(interval: Duration, name: String): Event[Tick] =
Expand All @@ -45,7 +43,7 @@ case class Tick(name: String)

This program produces a `scalaz.zio.IO` that can be run by e.g. `scalaz.zio.App` - see `TwoTickers.scala` in `examples`.

# Background
## Background

* _Functional Reactive Programming_ by Stephen Blackheath and Anthony Jones, Manning Publications
* Push-Pull Functional Reactive Programming [paper](http://conal.net/papers/push-pull-frp/) by Conal Elliot
Expand Down
5 changes: 5 additions & 0 deletions core/src/main/scala/scalaz/reactive/Behaviour.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ package scalaz.reactive

import scalaz.{ Applicative, Functor }

/**
* Semantically, a behaviour is simply a function of time. A reactive behaviour is composed
* of a discrete part, represented as a reactive value, `Reactive`, and a continuous
* part, represented as a time function,`TimeFun`.
*/
case class Behaviour[A](value: Reactive[TimeFun[A]]) extends AnyVal {

def map[B](f: A => B): Behaviour[B] =
Expand Down
17 changes: 17 additions & 0 deletions core/src/main/scala/scalaz/reactive/Event.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,23 @@ import scalaz.zio.{ Fiber, IO }

import scala.concurrent.duration.Duration

/**
* Semantically, an Event is time-ordered lists of future values, where a future value
* is a time/value pair: [(t0 , a0 ), (t1 , a1 ), ...]. If such an occurrence list is
* nonempty, another view on it is as a time t0, together with a reactive value having
* initial value a0 and event with occurrences [(t1,a1),...]. If the occurrence list is
* empty, then we could consider it to have initial time ∞ (maxBound), and reactive value
* of ⊥. Since a future value is a time and value, it follows that an event (empty or nonempty)
* has the same content as a future reactive value. This insight leads to a new representation
* of functional events:
*
* {{{
* -- for non-decreasing times
* newtype Event a = Ev (Future (Reactive a))
* }}}
*
* See more details in section 6 at http://conal.net/papers/push-pull-frp
*/
case class Event[+A](value: Future[Reactive[A]]) { self =>
def delay(interval: Duration): Event[A] = Event(value.delay(interval))

Expand Down
3 changes: 3 additions & 0 deletions core/src/main/scala/scalaz/reactive/Future.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package scalaz.reactive
import scalaz.Scalaz._
import scalaz.zio.IO

/**
* A value with an associated time, `(t,a)`
*/
object Future {

type Future[+A] = IO[Void, (Time, A)]
Expand Down
6 changes: 6 additions & 0 deletions core/src/main/scala/scalaz/reactive/Reactive.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ package scalaz.reactive
import scalaz.{ Applicative, Functor, Monad }
import Future._

/**
* A reactive value is like a reactive behaviour but is restricted to changing discretely. Its
* meaning is a step function defined by an initial value, `head`, and discrete changes, `tail`.
* Each discrete change is defined by a time and a value, which correspond exactly to an FRP `Event`.
* (See section 5.2 of Elliott's Push-Pull FRP paper)
*/
case class Reactive[+A](head: A, tail: Event[A]) {

def map[B](f: A => B): Reactive[B] =
Expand Down
3 changes: 3 additions & 0 deletions core/src/main/scala/scalaz/reactive/Sink.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package scalaz.reactive
import scalaz.zio.IO

/**
* A consumer for the generated values.
*/
object Sink {

type Sink[A] = A => IO[Void, Unit]
Expand Down
3 changes: 3 additions & 0 deletions core/src/main/scala/scalaz/reactive/TimeFun.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import scalaz.reactive.Time._
import scalaz.{ Applicative, Functor, Monad }
import scalaz.reactive.TimeFun.{ Fun, K }

/**
* A function of time. It has functor, applicative, and monad instances
*/
sealed trait TimeFun[+A] {

def apply: Time.T => A
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import java.awt.event._
import java.awt.{ BorderLayout, Dimension }
import java.util.EventObject

import javax.swing.{ JButton, JScrollPane, JTextArea, _ }
import javax.swing.{ JButton, JScrollPane, JTextArea, WindowConstants }
import scalaz.reactive.Event
import scalaz.reactive.Sink.Sink
import scalaz.zio.{ IO, _ }
Expand All @@ -20,7 +20,7 @@ object KeyboardAndTimeApp extends App with RTS {

class KeyboardAndTimeApp(name: String) extends AwtApp(name) {

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
val displayArea = new JTextArea
buildPane()

Expand Down