Functional Reactive Programming
Stephen Blackheath and Anthony Jones
Foreword by Heinrich Apfelmus
  • July 2016
  • ISBN 9781633430105
  • 360 pages
  • printed in black & white

A gentle introduction to the necessary concepts of FRP.

From the Foreword by Heinrich Apfelmus, author of the Reactive-banana FRP library

Functional Reactive Programming teaches the concepts and applications of FRP. It offers a careful walk-through of core FRP operations and introduces the concepts and techniques you'll need to use FRP in any language.

About the Technology

Today's software is shifting to more asynchronous, event-based solutions. For decades, the Observer pattern has been the go-to event infrastructure, but it is known to be bug-prone. Functional reactive programming (FRP) replaces Observer, radically improving the quality of event-based code.

About the book

Functional Reactive Programming teaches you how FRP works and how to use it. You'll begin by gaining an understanding of what FRP is and why it's so powerful. Then, you'll work through greenfield and legacy code as you learn to apply FRP to practical use cases. You'll find examples in this book from many application domains using both Java and JavaScript. When you're finished, you'll be able to use the FRP approach in the systems you build and spend less time fixing problems.

Table of Contents detailed table of contents

1. Stop listening!

1.1. Project, meet complexity wall

1.2. What is functional reactive programming?

1.2.1. Formal definition

1.2.2. Introducing Sodium

1.3. Where does FRP fit in? The lay of the land

1.4. Interactive applications: What are events?

1.5. State machines are hard to reason about

1.6. Interactive applications without the bugs

1.7. Listeners are a mainstay of event handling, but…​

1.8. Banishing the six plagues of listeners

1.9. Why not just fix listeners?

1.10. "Have you tried restarting it?" or why state is problematic

1.11. The benefit of FRP? Dealing with complexity

1.12. How does FRP work?

1.13. Paradigm shift

1.13.1. Paradigm

1.13.2. Paradigm shift

1.14. Think in terms of dependency

1.15. Thinking declaratively: What the program is, not what it does

1.16. A "hello world" GUI example

1.16.1. A button that clears a text field

1.17. A peek behind the scenes

1.18. Summary

2. Core FRP

2.1. The Stream type: a stream of events

2.1.1. A stream of events

2.2. The map primitive: transforming a value

2.2.1. Transforming a Stream

2.3. A quick recap: Stream and map

2.4. The components of an FRP system

2.4.1. Combining primitives

2.4.2. Separating I/O from logic

2.5. Referential transparency required

2.5.1. An exception: debugging

2.6. The Cell type: a value that changes over time

2.6.1. A trivial cell example

2.7. And you can map cells

2.8. The merge primitive: merging streams

2.8.1. Simultaneous events

2.8.2. How does merge do its job?

2.9. The coalesce primitive: coalescing simultaneous events

2.9.1. The function must be referentially transparent

2.10. The hold primitive: keeping state in a cell

2.10.1. Hold and simultaneous events

2.10.2. A quick recap: Cell and hold

2.11. The snapshot primitive: capturing the value of a cell

2.11.1. Variant that ignores the stream value

2.12. Looping hold and snapshot gives us an accumulator

2.12.1. Forward references

2.12.2. Construct your FRP inside an explicit transaction

2.12.3. Does snapshot see the new value or the old value?

2.13. The filter primitive: propagating an event only sometimes

2.13.1. Lecture time: referential transparency

2.14. The lift primitive: combining cells

2.14.1. lift is like a map for two or more cells

2.15. The never primitive: a stream that never fires

2.16. The constant primitive: A cell with a constant value

2.17. Referential transparency dos and don’ts

2.18. FRP cheat sheet

2.19. Summary

3. Some everyday widget stuff

3.1. Spinner as a standalone SWidget

3.2. Form validation

3.3. Summary

4. Writing a real application

4.1. The petrol pump example

4.2. Running the petrol pump example

4.3. Code, meet outside world

4.4. The life cycle of a petrol pump fill

4.4.1. Streams representing the start and end of the fill

4.4.2. The state of the fill

4.5. Is this really better?

4.6. Counting liters delivered

4.7. Showing dollars delivered

4.8. Communicating with the point-of-sale system

4.9. Modularity illustrated: A keypad module

4.10. Notes about modularity

4.10.1. The form of a module

4.10.2. Tuples vs. classes

4.10.3. Explicit wiring

4.10.4. When inputs and outputs proliferate

4.10.5. Some bugs solved, some not

4.10.6. When inputs and outputs proliferate

4.10.7. Some bugs solved, some not

4.10.8. Testability

4.11. Adding a preset dollar amount

4.12. What have we achieved?

4.13. Summary

5. New concepts

5.1. In search of the mythical von Neumann machine

5.1.1. Why so slow? The cache

5.1.2. The madness of bus optimization

5.2. Compositionality

5.2.1. Reductionism and engineering

5.3. Lack of compositionality illustrated

5.3.1. Lack of compositionality

5.4. Compositionality: Eliminating whole classes of bugs

5.5. Don’t pull out the rug: use immutable values

5.5.1. Immutable data structures

5.6. Clarity of intent

5.7. The consequences of cheap abstraction

5.8. Summary

6. FRP on the web

6.1. Rx.JS

6.2. Observable

6.3. How to maintain state

6.3.1. A stateful accumulator with scan()

6.4. The most recent value of an observable with withLatestFrom()

6.5. Keeping state - in Rx.JS, Kefir.JS and Flapjax

6.5.1. startWith() as shorthand for BehaviorSubject

6.5.2. The same again with Kefir.JS

6.5.3. And now…​ Flapjax

6.6. The latest of two observables with combineLatest()

6.6.1. Glitches in combineLatest

6.6.2. merge() is not compositional

6.7. Create your own hot observable

6.8. Example: Autocomplete the FRP way

6.9. Rx.JS/Sodium cheat sheet

6.10. Static typing preferred

6.11. Summary

7. Switch

7.1. The sample primitive: Getting a cell’s value

7.2. Switch

7.2.1. The concept of switch: a TV remote control

7.3. Switch use case #1: Zombies

7.3.1. The end of the world

7.3.2. A simple human

7.3.3. You can use sample inside map or snapshot

7.3.4. A game loop

7.3.5. An enhanced obstacle-avoiding human

7.3.6. A flesh-eating zombie

7.3.7. Putting the two characters together

7.4. Transforming the game character with switch

7.4.1. Switch and memory management

7.5. Switch use case #2: Creation and destruction of game characters

7.5.1. Not quite referentially transparent

7.5.2. Another "what are we doing this for" moment

7.5.3. An exercise for the reader

7.5.4. The efficiency of big merges

7.5.5. Efficiency of this approach

7.6. Switch use case #3: Removing invalid states

7.6.1. And now, improved with flatMap

7.7. Switch use case #4: Switching between "screens"

7.8. Summary

8. Operational primitives

8.1. Interfacing FRP code with the rest of your program

8.1.1. Sending and listening to streams

8.1.2. Sending and listening to cells

8.1.3. Threading model and callback requirements

8.2. Laziness solves loop craziness

8.3. Transactions

8.3.1. Constructing FRP logic under an explicit transaction

8.4. Getting a stream from a cell with updates and value

8.4.1. Introducing updates and value

8.5. Spawning new transactional contexts with the split primitive

8.5.1. deferring a single event to a new transaction

8.6. Scalable addressing

8.7. Summary

9. Continuous time

9.1. "Rasterizing" time

9.2. Position as a function of time

9.3. The animation loop

9.4. Measuring time

9.4.1. "Signals" for quadratic motion

9.4.2. A natural representation of a bouncing ball

9.5. Summary

10. Battle of the Paradigms

10.1. Classic state machine vs. FRP vs. actor model

10.1.1. Classic state machine

10.1.2. FRP

10.1.3. Actor model

10.1.4. And the winner is…​

10.2. Let’s add a feature: SHIFT key gives axis lock

10.3. Improvement: Shift key updates document

10.3.1. Changing this in the classic paradigm

10.3.2. Changing this in FRP

10.3.3. Changing this in the actor model

10.3.4. How are the different paradigms doing?

10.4. Summary

11. Programming in the real world

11.1. Dealing with I/O

11.1.1. Error handling in FRP

11.1.2. Executing an I/O action

11.1.3. Putting the application together

11.2. Promises/Futures

11.2.1. A map viewer example using Promise

11.2.2. Spawning the server request

11.3. Distributed Processing

11.3.1. Sacrificing consistency

11.3.2. A stream that goes over a network connection

11.4. Unit testing

11.4.1. Unit testing FRP code

11.4.2. We don’t recommend test-driven development (TDD)

11.4.3. FRP is “type-driven development”

11.4.4. FRP code is safe to refactor

11.4.5. FRP code is inherently “testable”

11.4.6. Test your logic

11.5. Summary

12. Helpers and Patterns

12.1. Calming: Removing duplicate values

12.2. Pausing a game

12.3. Junction or client registry

12.4. Writable remote values

12.5. Persistence

12.6. Unique ID generation

12.7. An FRP-based GUI system

12.7.1. Drawable

12.7.2. Fridget

12.7.3. Our first fridget: FrButton

12.7.4. Bringing a Fridget to life with FrView

12.7.5. Layout

12.8. A form with text fields

12.9. Summary

13. Refactoring

13.1. To refactor or not to refactor?

13.2. Drag and drop example

13.2.1. Coding it the traditional way

13.3. The FRP way: diagrams to code

13.4. Add a feature: Draw the floating element

13.5. Fix a bug: Clicks are being treated as drags

13.6. FRP: refactoring is a breeze

13.7. Summary

14. Adding FRP to existing projects

14.1. Where can FRP help?

14.2. Change to immutable data structures

14.3. Stream as a drop-in replacement for callbacks

14.3.1. Caveat: You can’t send() inside a listener

14.3.2. Choose the right chunk size

14.4. Program initialization with One Big Transaction

14.5. Module extensibility with Junction/client registry

14.6. Cells can replace mutable variables

14.7. Summary

15. Future directions

15.1. Performance

15.2. Pre-compiled FRP for performance or embedded systems

15.3. Parallelism

15.4. Syntax improvements

15.4.1. Auto-lifting

15.4.2. Implicit forward references

15.4.3. Infix operators

15.4.4. Type inference

15.5. Standardization and code re-use

15.5.1. Code re-use and FRP abstractions

15.5.2. FRP engine performance

15.5.3. Common syntax between languages

15.6. FRP database applications

15.7. Visualization and debugging tools

15.8. Visual programming

15.9. Reactoring tools

15.10. Summary


Appendix A: Sodium API

Appendix B: The six plagues of event handling

Appendix C: Comparison of FRP systems

Appendix D: A section for managers

Appendix E: Denotational semantics

What's inside

  • Think differently about data and events
  • FRP techniques for Java and JavaScript
  • Eliminate Observer one listener at a time
  • Explore Sodium, RxJS, and Kefir.js FRP systems

About the reader

Readers need intermediate Java or JavaScript skills. No experience with functional programming or FRP required.

About the authors

Stephen Blackheath and Anthony Jones are experienced software developers and the creators of the Sodium FRP library for multiple languages.

Illustrated by Duncan Hill.

placing your order...

Don't refresh or navigate away from the page.
print book $29.99 $49.99 pBook + eBook + liveBook
Additional shipping charges may apply
Functional Reactive Programming (print book) added to cart
continue shopping
go to cart

eBook $24.99 $39.99 3 formats + liveBook
Functional Reactive Programming (eBook) added to cart
continue shopping
go to cart

Prices displayed in rupees will be charged in USD when you check out.

FREE domestic shipping on three or more pBooks