+ - 0:00:07
Notes for current slide
Notes for next slide

Explicitly Comprehensible Functional Reactive Programming

Steve Krouse

1 / 19

This talk is about

1) the comprehensibility

When making a change, it's the first and most-time-consuming step.

2) of large

Software today is 10k lines minimum but goes up to millions.

3) FRP applications.

They are becoming increasingly prevalent.

2 / 19

This this talk does not have The AnswerTM

I complain about where we are, and point us in a promising direction.

3 / 19

FP is comprehensible

1) Local reasoning

Code elsewhere cannot affect this code via side-effects.

2) Explicit data dependencies

We can grok this code by reading its dependency definitions recursively.

4 / 19

FP is not always comprehensible

There is in principle nothing to stop functional programs from passing a single extra parameter into and out of every single function in the entire system. If this extra parameter were a collection (compound value) of some kind then it could be used to simulate an arbitrarily large set of mutable variables...

...ease of reasoning is lost (we still know that each function is dependent only upon its arguments, but one of them has become so large and contains irrelevant values that the benefit of this knowledge as an aid to understanding is almost nothing). This is however an extreme example and does not detract from the general power of the functional approach

-- Out of the Tarpit (Moseley and Marks)

5 / 19

This "extreme example" has become the most popular pattern in FRP!

6 / 19

The Elm Architecture

7 / 19

Elm Counter

0
01 type alias Model = { count : Int }
02
03 initialModel : Model
04 initialModel = { count = 0 }
05
06 type Msg = Increment | Decrement
07
08 update : Msg -> Model -> Model
09 update msg model = case msg of
10 Increment -> { model | count = model.count + 1 }
11 Decrement -> { model | count = model.count - 1 }
12
13 view : Model -> Html Msg
14 view model = div []
15 [ button
16 [ onClick Increment ]
17 [ text "+1" ]
18 , span [] [ text <| toString model.count ]
19 , button
20 [ onClick Decrement ]
21 [ text "-1" ]
22 ]
8 / 19

Elm Todo MVC

Add ->
{ model
| uid = model.uid + 1
, field = ""
, entries = if String.isEmpty model.field
then model.entries
else model.entries ++ [newEntry model.field model.uid ]
}
9 / 19

Elm TodoMVC diagram

10 / 19

Elm TodoMVC Ctl-F "entries ="

11 / 19

Elm TodoMVC Ctl-F "entries =" messages

12 / 19

Reflex FRP

haskell, ghcjs

1) higher order

Stream can contain streams

2) cyclic

Streams can refer to streams that refer to themselves

13 / 19

Reflex Counter

01 button :: Text -> m (Event ())
02 el :: Text -> m a -> m a
03 display :: Show a => Dynamic a -> m ()
04 (<$) :: a -> Event b -> Event a
05 leftmost :: [Event a] -> Event a
06 foldDyn :: (a -> b -> b) -> b -> Event a -> m (Dynamic b)
09
08 bodyElement :: MonadWidget t m => m ()
09 bodyElement = do
10 rec evIncr <- button "+1"
11 el "div" $ display count
12 evDecr <- button "-1"
13 count <- foldDyn (+) 0 $ leftmost
14 [ 1 <$ evIncr
15 , -1 <$ evDecr
16 ]
17 return ()
18
19 main :: IO ()
20 main = mainWidget bodyElement
14 / 19

Reflex TodoMVC Entries

01 initialTasks :: Map Int Task
02 initialTasks = Map.empty
03
04 insertNew_ :: Task -> Map Int Task -> Map Int Task
05
06 todoMVC :: (DomBuilder t m, MonadFix m, MonadHold t m) => m ()
07 todoMVC = do
08 el "div" $ do
09 elAttr "section" ("class" =: "todoapp") $ do
10 mainHeader
11 rec tasks <- foldDyn ($) initialTasks $
12 mergeWith (.)
13 [ fmap insertNew_ newTask
14 , listModifyTasks
15 , fmap (const $ Map.filter $ not . taskCompleted) clearCompleted
16 ]
17 newTask <- taskEntry
18 listModifyTasks <- taskList activeFilter tasks
19 (activeFilter, clearCompleted) <- controls tasks
20 return ()
21 infoFooter

Cycle: tasks depends upon listModifyTasks and clearCompleted, which depend upon tasks

15 / 19

Reflex TodoMVC Diagram

16 / 19

Reflex TodoMVC Diagram (Simplified)

17 / 19

Is the cure worse than the disease?

- Serializeable Elm singleton -> time travel debugging, hot reloading

- Reflex + ghcjs is annoying

18 / 19

Conclusion

I hope you are now unhappy with where we are. And excited to look for other solutions. Such a higher-order and cyclic streams. So that we can... (please forgive me)

19 / 19

Reflex TodoMVC Diagram (Simplified)

17 / 19
Paused

Help

Keyboard shortcuts

, , Pg Up, k Go to previous slide
, , Pg Dn, Space, j Go to next slide
Home Go to first slide
End Go to last slide
Number + Return Go to specific slide
b / m / f Toggle blackout / mirrored / fullscreen mode
c Clone slideshow
p Toggle presenter mode
t Restart the presentation timer
?, h Toggle this help
Esc Back to slideshow
Edit in JS Bin