## Functional interactive behavior

In a previous post, I presented a fundamental reason *why classic FRP does not fit interactive behavior*, which is that the semantic model captures only the influence of time and not other input.
I also gave a simple alternative, with a simple and general model for temporal and spatial transformation, in which input behavior is transformed inversely to the transformation of output behavior.

The semantic model I suggested is the same as used in “Arrow FRP”, from Fruit and Yampa. I want, however, a more convenient and efficient way to package up that model, which is the subject of the post you are reading now.

Next, we took a close look at one awkward aspect of classic FRP for interactive behavior, namely the need to trim inputs, and how trimming relates to comonadic FRP.
The `trim`

function allows us to define multi-phase interactive behaviors correctly and efficiently, but its use is tedious and is easy to get wrong.
It thus fails to achieve what I want from functional programming in general and FRP in particular, which is to enable writing simple, natural descriptions, free of mechanical details.

The current post hides and automates the mechanics of trimming, so that the intent of an interactive behavior can be expressed directly and executed correctly and efficiently.

As before, I’ll adopt two abbreviations, for succinctness:

```
type B = Behavior
type E = Event
```

### Safe and easy trimming

Previously, I defined an interactive cat behavior as follows:

```
cat3 :: B World -> B Cat
cat3 world = sleep world `switcher`
((uncurry prowl <$> trimf wake world) `mappend`
(uncurry eat <$> trimf hunger world))
```

I’d really like to write the following

```
-- ideal:
cat4 = sleep `switcher` ((prowl <$> wake) `mappend` (eat <$> hunger))
```

Let’s see how close we can get.

I can see right off I’ll have to replace or generalize `switcher`

.
For now, I’ll replace it:

```
switcherf :: (B i -> B o)
-> (B i -> E (B i -> B o))
-> (B i -> B o)
```

This function will have to manage trimming:

```
bf `switcherf` ef = i ->
bf i `switcher` (uncurry ($) <$> trimf ef i)
```

I won’t have to replace `mappend`

, since it’s a method and so can have a variety of types.
In this case, `mappend`

applies to a function from behaviors to events.
Fortunately, the function monoid is exactly what we need:

```
instance Monoid b => Monoid (a -> b) where
mempty = const mempty
f `mappend` g = a -> f a `mappend` f b
```

or the more lovely standard form for applicative functors:

```
instance Monoid b => Monoid (a -> b) where
mempty = pure mempty
mappend = liftA2 mappend
```

The use of `(<$>)`

(i.e., `fmap`

) in `cat4`

above won’t work.
We want instead to `fmap`

inside the *result* of a function from behaviors to events.
Using the style of semantic editor combinators, we get the following definition, which is fairly close to our ideal:

```
cat4 = sleep `switcherf`
((result.fmap) prowl wake `mappend` (result.fmap) eat hunger)
```

### Generalized switching

To generalize `switcher`

, introduce a new type class:

```
class Switchable b e where switcher :: b -> e b -> b
```

The original Reactive `switcher`

is a special case:

```
instance Switchable (B a) E where switcher = R.switcher
```

We can switch among tuples and among other containers of switchables. For instance,

```
instance (Functor e, Switchable b e, Switchable b' e)
=> Switchable (b,b') e where
(b,b') `switcher` e = ( b `switcher` (fst <$> e)
, b' `switcher` (snd <$> e) )
```

### Temporal values

Looking through the examples above, all we really had to do with the input behavior was to compute all remainders. I used

```
duplicate :: B a -> B (B a)
```

More generally,

```
class Temporal a where remainders :: a -> B a
```

Behaviors and events are included as a special case,

```
instance Temporal (B a) where remainders = duplicate
instance Temporal (E a) where remainders = ...
```

Temporal values combine without losing their individuality, which allows efficient change-driven evaluation as in *Simply efficient functional reactivity*:

```
instance (Temporal a, Temporal b) => Temporal (a,b) where
remainders (a,b) = remainders a `zip` remainders b
```

Similarly for other triples and other data structures.

Sometimes it’s handy to carry static information along with dynamic information. Static types can be made trivially temporal:

```
instance Temporal Bool where remainders = pure
instance Temporal Int where remainders = pure
-- etc
```

With this `Temporal`

class, the trimming definitions above have more general types.

```
trim :: Temporal i => E o -> i -> E (o, i)
trimf :: Temporal i => (i -> E o) -> (i -> E (o, i))
```

As does function switching:

```
switcherf :: (Temporal i, Switchable o E) =>
(i -> o) -> (i -> E (i -> o)) -> i -> o
```

### Types for functional interactive behavior

We’ve gotten almost to my ideal cat definition.
We cannot, however, use `switcher`

or `(<$>)`

here with functions from behaviors to behaviors, because the types don’t fit.

To cross the last gap, let’s define new types corresponding to the idioms we’ve seen repeatedly above.

```
-- First try
type i :~> o = BI (B i -> B o)
type i :-> o = EI (B i -> E o)
```

Or, using type composition:

```
-- Second try
type (:~>) i = (->) (B i) :. B
type (:->) i = (->) (B i) :. E
```

The advantage of type composition is that we get some useful definitions for free, including `Functor`

and `Applicative`

instances.

However, there’s a problem with both versions. They limit us to a single behavior as input. A realistic interactive environment has many inputs, including a mixture of behaviors and events.

In Yampa, that mixture is combined into a single behavior, leading to two difficulties:

- The distinction between behaviors and events gets lost, as well as (I think) accurate and minimal-latency event detection and response.
- The bundled input environment changes whenever any component changes, leading to everything getting recomputed and redisplayed when anything changes.

To avoid these problems, I’ll take a different approach.
Generalize inputs from behaviors to arbitrary `Temporal`

values, which include behaviors, events and tuples and structures of temporal values.

The types for interactive behaviors and interactive events are

```
type (:~>) i = (->) i :. B
type (:->) i = (->) i :. E
```

So `i :~> o`

is like `i -> B o`

, and `i :-> o`

is like `i -> E o`

.

Switching for interactive behaviors wraps the `switcherf`

function from above:

```
instance Temporal i => Switchable (i :~> o) ((:->) i) where
switcher = inO2 $ bf ef -> bf `switcherf` (result.fmap) unO ef
```

The `inO2`

and `unO`

functions from TypeCompose just manipulate `newtype`

wrappers.
See *Prettier functions for wrapping and wrapping*.

This definition is actually more general than the type given here.
For instance, it can be used to switch between interactive *events* as well as interactive *behaviors*.
To see the generalization, first abstract out the commonality between `(:~>)`

and `(:->)`

:

```
type i :->. f = (->) i :. f
type (:~>) i = i :->. B
type (:->) i = i :->. E
```

The same instance code but with a more general type:

```
instance (Temporal i, Switchable (f o) E)
=> Switchable ((i :->. f) o) ((:->) i) where
switcher = inO2 $ bf ef -> bf `switcherf` (result.fmap) unO ef
```

We can also switch between interactive *collections* of behaviors and events, though not with the `(:->.)`

wrapping.

### Where are we?

Almost all of the pieces are in place now.
Another post will relate input trimming to the time transformation of interactive behaviors, as discussed in
*Why classic FRP does not fit interactive behavior*.
Also, how interactive FRP relates to *Sequences, segments, and signals*.

## Leave a comment