aa r X i v : . [ c s . P L ] O c t Adjoint Reactive GUI Programming
Christian Uldal Graulund − − − , Dmitrij Szamozvancev , and NeelKrishnaswami − − − IT University of Copenhagen, 2300 Copenhagen, DK [email protected] University of Cambridge, Cambridge CB3 0FD, UK [email protected],[email protected]
Abstract.
Most interaction with a computer is done via a graphical user interface. Tra-ditionally, these are implemented in an imperative fashion using shared mutable state andcallbacks. This is efficient, but is also difficult to reason about and error prone. Functional Re-active Programming (FRP) provides an elegant alternative which allows GUIs to be designedin a declarative fashion. However, most FRP languages are synchronous and continually checkfor new data. This means that an FRP-style GUI will “wake up” on each program cycle. Thisis problematic for applications like text editors and browsers, where often nothing happensfor extended periods of time, and we want the implementation to sleep until new data arrives.In this paper, we present an asynchronous
FRP language for designing GUIs called λ Widget .Our language provides a novel semantics for widgets, the building block of GUIs, which offersboth a natural Curry–Howard logical interpretation and an efficient implementation strategy.
Keywords:
Linear Types · Reactive Programming · Asynchronous Programming · GraphicalUser Interfaces
Many programs, like compilers, can be thought of as functions – they take a single input (a sourcefile) and then produce an output (such as a type error message). Other programs, like embeddedcontrollers, video games, and integrated development environments (IDEs), engage in a dialoguewith their environment: they receive an input, produce an output, and then wait for a new inputthat depends on the prior input, and produce a new output which is in turn potentially based onthe whole history of prior inputs.Our usual techniques for programming interactive applications are often very confusing, becausethe different parts of the program are not written to interact via structured control flow (i.e., bypassing and return values from functions, or iterating over data in loops). Instead, they communicateindirectly, by registering state-manipulating callbacks with one another, which are then implicitlyinvoked by an event loop. This makes program reasoning very challenging, since each of thesefeatures – aliased mutable state, higher-order functions, and concurrency – represents a seriousobstacle on its own, and interactive programs rely upon their combination .This challenge has led to a great deal of work on better abstractions for programming reactivesystems. Two of the main lines of work on this problem are synchronous dataflow and functionalreactive programming . The synchronous dataflow languages, like Esterel [5], Lustre [9], and LucidSynchrone [28], feature a programming model inspired by Kahn networks. Programs are networks ofstream-processing nodes which communicate with each other, each node consuming and producinga fixed number of primitive values at each clock tick. The first-order nature of these languages makes
Graulund et al. them strongly analysable, which lets them offer powerful guarantees on space and time usage. Thismeans they see substantial use in embedded and safety-critical contexts.Functional reactive programming, introduced by Elliott and Hudak [13], also uses time-indexedvalues, dubbed signals, rather than mutable state as its basic primitive. However, FRP differs fromsynchronous dataflow by sacrificing static analysability in favour of a much richer programmingmodel. Signals are true first-class values, and can be used freely, including in higher-order functionsand signal-valued signals. This permits writing programs with a dynamically-varying dataflow net-work, which simplifies writing programs (such as GUIs) in which the available signals can changeas the program executes. Over the past decade, a long line of work has refined FRP via the Curry–Howard correspondence [21,18,17,19,20,10,1]. This approach views functional reactive programs asthe programming counterpart for proofs of formulas in linear temporal logic [27], and has enabledthe design of calculi which can rule out spacetime leaks [20] or can enforce temporal safety andliveness properties [10].However, both synchronous dataflow and FRP (in both original and modal flavours) have a synchronous (or “pull”) model of time – time passes in ticks, and the program wakes up on everytick to do a little bit more computation. This is suitable for applications in which something newhappens at every time step (e.g., video games), but many GUI programs like text editors andspreadsheets spend most of their time doing nothing. That is, even at each event, most of theprogram will continue doing nothing, and we only want to wake up a component when an eventdirectly relevant to it occurs. This is important both from a performance point of view, as well asfor saving energy (and extending battery life). Because of this need, most GUI programs continueto be written in the traditional callbacks-on-mutable-state style.In this paper, we give a reactive programming language whose type system both has a verystraightforward logical reading, and which can give natural types to stateful widgets and the event-based programming model they encourage. We also derive a denotational semantics of the language,by first working out a semantics of widgets in terms of the operations that can be performed uponthem and the behaviour they should exhibit. Then, we find the categorical setting in which thewidget semantics should live, and by studying the structure this setup has, we are able to interpretall of the other types of the programming language.
The contributions of this paper are as follows: – We give a descriptive semantics for widgets in GUI programming, and show that this semanticscorrectly models a variety of expected behaviours. For example, our semantics shows that awidget which is periodically re-set to the colour red is different from a widget that was onlypersistently set to the colour red at the first timestep. Our semantic model can show that aslong as neither one is updated, they look the same, but that they differ if they are ever set toblue – the first will return to red at reset time, and the second will remain blue. – From this semantics, we find a categorical model within which the widget semantics naturallyfits. This model is a Kripke–Joyal presheaf semantics, which is morally a “proof-relevant” Kripkemodel of temporal logic. – We give a concrete calculus for event-based reactive programming, which can be implemented interms of the standard primitives for modern GUI programming, scene graphs (or DOM) whichare updated via callbacks invoked upon events. We then show that our model can soundly djoint Reactive GUI Programming 3 interpret the types of our calculus in an entirely standard way, showing that the types of ourreactive programming language can be interpreted as time-varying sets. – Furthermore, this calculus has an entirely standard logical reading in terms of the Curry–Howardcorrespondence. It is a “linear temporal linear logic”, with the linear part of the languagecorresponding to the Benton–Wadler [3] LNL calculus for linear logic, and the temporal part ofthe language corresponding to S4.3 linear temporal logic. We also give a proof term for the S t select primitive ofconcurrent programming. In this section we give an informal presentation of λ Widget through the API of the
Widget type. ThisAPI mirrors how one would work with a GUI at the browser level. An important feature of a well-designed GUI is that it should not do anything when not in use. In particular, it should not checkfor new inputs in each program cycle ( pull -based reactive programming), but rather sleep until newdata arrives ( push -based reactive programming). Many FRP languages are synchronous languagesand have some internal notion of a timestep. These languages are mostly pull-based, whereas moretraditional imperative reactive languages are push-based. The former have clear semantics and areeasy to reason about, the latter have efficient implementations. In λ Widget we would like to combinethese aspects and get a language that is easy to reason about with an efficient implementation.In general, we think of a widget as a state through time , i.e., at each timestep, the widget is insome state which is presented to the user. The widget is modified by commands , which can updatethe state. To program with widgets, the programmer applies commands at various times.The proper type system for a language of widgets should thus be a system with both stateand time. If we consider what a logic for widgets should be, there are two obvious choices. A logicfor state is linear logic [14], and a logic for time is linear temporal logic [27]. The combination ofthese two is the correct setting for a language of widgets, and, going through Curry–Howard, thecorresponding type theory is a linear, linear temporal type theory.
To work with widgets, we define a API which mirrors how one would work with a browser levelGUI: newWidget : I ⊸ ∃ ( i : Id ) , Widget i dropWidget : ∀ ( i : Id ) , Widget i ⊸ IsetColor : ∀ ( i : Id ) , F Color ⊗ Widget i ⊸ Widget i onClick : ∀ ( i : Id ) , Widget i ⊸ Widget i ⊗ IonKeypress : ∀ ( i : Id ) , Widget i ⊸ Widget i ⊗ ( F Char ) out : A ⊸ ∃ ( n : Time ) , A @ n into : ∃ ( n : Time ) , A @ n ⊸ A split : ∀ ( i : Id ) ( t : Time ) , Widget i ⊸ Prefix i t ⊗ ( Widget i ) @ t join : ∀ ( i : Id ) ( t : Time ) , Prefix i t ⊗ ( Widget i ) @ t ⊸ Widget i The first two commands creates and deletes widgets, respectively. The ⊸ should be understoodas state passing . We read the type of newWidget as “consuming no state, produce a new identifier Graulund et al. index and a widget with that identifier index”. The identifier indices are used to ensure the correctbehavior when using the split and join commands explained below. The existential quantificationdescribes the non-deterministic creation of an identifier index. The use of non-determinism is crucialin our language and will be explaining in further detail in section 4. Since λ Widget has a linear typesystem, we need an explicit construction to delete state. For widgets, this is dropWidget . The type isread as “for any identifier index, consume a widget with that identifier index and produce nothing”.The first command that modifies the state of a widget is setColor . Here we see the adjointnature of the calculus with
F Color . A color is itself not a linear thing, and as such, to use it inthe linear setting, we apply F , which moves from the non-linear (Cartesian) fragment and intothe linear fragment. The second new thing is the linear product ⊗ . This differs from the regularnon-linear product in that we do not have projection maps. Again, because of the linearity of ourlanguage, we cannot just discard state. We can now read the type of setColor as “Given a color anda identified widget, consume both and produce a new widget”. The produced widget is the sameas the consumed widget, but with the color attribute updated.The next two commands, onClick and onKeypress , are roughly similar. Both register a handleon the widget, for a mouse click and a key press, respectively. Here we see the first use of the modality, which represents an event . The type A represents that at some point in the future wewill receive something of type A . Importantly, because of the asynchronous nature of λ Widget , wedo not know when it happens. We can then read the type of onClick as “Consuming an identifiedwidget, produce an updated widget together with a mouse click event”. The same holds for thetype of onKeypress except a key press event is produced.The two commands out and into allows us to work with events in a more precise way. Given anevent, we can use out to “unfold” it into an existential. The @ connective describes a type that isonly available at a certain timestep, i.e., A @ n means “at the timestep n , a term of type A will beavailable”. The into commands is the reverse of out and turns an existential and an @ into an event.So far, we have only applied commands to a widget in the current timestep, but to programappropriately with widgets, we should be able to react to events and apply commands “in thefuture”. This is exactly what the split and join commands allows us to do. The type of split isread as “Given any time step and any identified widget, split the widget into all the states before that time and the widget at that time”. We denote the collection of states before a given time a prefix and give it the type Prefix . Given the state of the widget at a given timestep, we can nowapply commands at that timestep . Note that both the prefix and the widget is indexed by the sameidentifier index. This is to ensure that when we use join , we combined the correct prefix and future.
To see the API in action, we now proceed with several examples of widget programming. For eachexample, we will add a comment on each line with the type of variables, and then explain theexample in text afterwards.One of the simplest things we can do with a widget is to perform some action when the widgetis clicked. In the following example, we register a handler for mouse clicks, and then we use theclick event to change the color of the widget to red at the time of the click. To do this, we use the out map to get the time of the event, then we split the widget and apply setColor at that point inthe future. turnRedOnClick : ∀ ( i : Id ) , Widget i ⊸ Widget i turnRedOnClick i w = djoint Reactive GUI Programming 53 let ( w , c ) = onClick i w in -- w : Widget i, c : I . let unpack ( x , c ) = out c in -- x : Time , c : I @ x . let c @ x = c in -- c : I at the time x . let hi @ x = c in let ( p , w ) = split i x w in -- p : Prefix i x, w : Widget i @ x . let w @ x = w in -- w : Widget i at the time x . let w = ( setColor ( F Red ) w ) @ x in -- w : Widget i @ x . join i x ( p , w )To see why this type checks, we go through the example line by line. In line 3, we register a handlefor a mouse click on the widget. In line 4, we turn the click event into an existential. In line 5, weget c which is a binding that is only available at the timestep x . Since we only need the time of theclick, we discharge the click itself in line 6. In line 7 and 8, we split the widget using the timestep x and bind w to the state of the widget at that timestep. In line 9, we change the color of the widgetto red at x and in line 10 we recompose the widget.In general, we will allow pattern matching in eliminations and since widget identity indices canalways be inferred, we will omit them. In this style, the above example become: turnRedOnClick : ∀ ( i : Id ) , Widget i ⊸ Widget i turnRedOnClick w = let ( w , c ) = onClick w in -- w : Widget i, c : I . let unpack ( x , hi @ x ) = out c in -- x : Time . let ( p , w @ x ) = split x w in -- p : Prefix i x, w : Widget i at the time x . join x ( p , ( setColor ( F Red ) w ) @ x )We will use the same sugared style throughout the rest of the examples.The above example turns a widget red exactly at the time of the mouse click, but will notdo anything with successive clicks. To also handle further mouse clicks, we must register an eventhandler recursively . This is a simple modification of the previous code: keepTurningRed : ∀ ( i : Id ) , Widget i ⊸ Widget i keepTurningRed w = let ( w , c ) = onClick w in -- w : Widget i, c : I . let unpack ( x , hi @ x ) = out c in -- x : Time . let ( p , w @ x ) = split x w in -- p : Prefix i x, w : Widget i at the time x . join ( p , ( setColor ( F Red ) ( keepTurningRed w ) @ x ))By calling itself recursively, this function will make sure a widget will always turn red on a mouseclick.To understand the difference between two above examples, consider the following code exampleWidget : ∀ ( i : Id ) , Widget i ⊸ Widget i exampleWidget w = turnBlueOnClick ( keepTurningRed w )where w is some widget and turnBlueOnClick is the obvious modification of the above code. Onthe first click, the widget will turn blue, on the second click it will turn red and on any subsequentclick, it will keep turning red, i.e., stay red unless further modified.When working with widgets, we will often register multiple handlers on a single widget. Forexample, a widget should have one behavior for a click and another behavior for a key press. Graulund et al.
To choose between two events, we use the select construction. This construction is central to ourlanguage and how to think about a push-based reactive language.Given two events, t : A, t : B , there are three possible behaviors: Either t returns first,and we wait for t or t returns first and we wait for t or they return at the same time. In general,we want to select between n events, but if we need to handle all possible cases, this will give 2 n cases, so to keep the syntax linear in size, we will omit the last case. In the case events actually return at the same time, we do a non-deterministic choice between them. The syntax for select is select ( t as x t ′ | t as y t ′ )where x : A, y : B, t ′ : A ⊸ B ⊸ C and t ′ : B ⊸ A ⊸ C . The second important thing tounderstand when working with select is that given we are working with events, we do not actuallyknow at which timestep the events will trigger, and hence, we do not know what the (linear) contextcontains. Thus, when using select , we will only know either a : A, t : B or t : A, b : B . We canthink of the select rule a case-expression that must respect time.In the following example, we register two handlers, one for clicks and one for key presses, andchange the color of the widget based on which returns first. widgetSelect : ∀ ( i : Id ) , Widget i ⊸ Widget i widgetSelect w = let ( w , c ) = onClick w in -- w : Widget i, c : I . let ( w , k ) = onKeypress w in -- w : Widget i, k : ( F char ). let col = -- col : ( F Color ) select ( c as x → let hi = x in -- x : I , k : ( F Color ). evt ( F Red ) | k as y → let F k ′ = y in -- y : F char , c : I evt ( F Blue )) let unpack ( x , col ′ @ x ) = out col in -- x : Time , col ′ : F Color at the time x . let ( p , w @ x ) = split x w in -- p : Prefix i x, w : Widget i at the time x . join ( p , ( setColor col ′ w ) @ x )In line 3 and 4, we register the two handlers. In line 5-9, we use the select construction. In the firstcase, the click happens first and we return the color red. In the second case, the key press happensfirst and we return the color blue. In both cases, because of the linear nature of the language, weneed to do a let-binding to discharge the unit and the char, respectively. In line 10, we turn thecolor event into an existential. In line 11, we use the timestep of the color event to split the widget,and in line 12, we change the color of the widget at that time and recompose it.To see how λ Widget differs from more traditional synchronous FRP languages, we will examinehow to encode a kind of streams. Since our language is asynchronous , the stream type must beencoded as
Str A := να. ( A ⊗ α )This asynchronous stream will at some point in the future give a head and a tail. We do not knowwhen the first element of the stream will arrive, and after each element of the stream is produced,we will wait an indeterminate amount of time for the next element. The reason why the streamtype in λ Widget must be like this is essentially that we want a push-based language, i.e., we do notwant to wake up and check for new data in each program cycle. Instead, the program should sleepuntil new data arrives. djoint Reactive GUI Programming 7
To show the difference between the asynchronous stream and the more traditional synchronousstream, we will look at some examples. With a traditional stream, a standard operation is zippingtwo streams: that is, given
Str A and Str B , we can produce Str A × B , which should be the element-wise pairing of the two streams. It should be clear that this is not possible for our asynchronousstreams. Given two streams, we can wait until the first stream produces an element, but the secondstream may only produce an element after a long period of time. Hence, we would need to bufferthe first element, which is not supported in general. Remember, when using select , we can not useany already defined linear variables, since we do not know if they will be available in the future.Rather than zipping stream, we can instead do a kind of interleaving as shown below. We use fold and unfold to denote the folding and unfolding of the fixpoint. interleave : Str A ⊸ Str B ⊸ Str ( A ⊕ B ) interleave xs ys = fold ( select ( unfold xs as xs ′ → let ( x , xs ′′ ) = xs ′ in -- xs ′ : A ⊗ Str
A, x : A, xs ′′ : Str A evt ( inl x , interleave xs ′ ys ) | unfold ys as ys ′ → let ( y , ys ′′ ) = ys ′ in -- ys ′ : B ⊗ Str
B, y : B, ys ′′ : Str A evt ( inr y , interleave xs ys ′ )))Here, we use select to choose between which stream returns first, and then we let that element bethe first element of the new stream.On the other hand, some of the traditional FRP functions on streams can be translated. Forinstance, we can map of function over a stream, given that it is available at each step in time : map : F ( G ( A ⊸ B )) ⊸ Str A ⊸ Str B map f xs = let F f = f in -- f : G ( A ⊸ B ) in Cartesian context let ( y , ( x , xs ′ ) @ y ) = out ( unfold xs ) in -- y : Time and x : A, xs ′ , Str A at the time y . fold ( evt (( runG f ) x , map f xs ′ ))The type F ( G ( A ⊸ B )) is read as a linear function with no free variables that can be used in a non-linear fashion, i.e., duplicated. This restriction to such “globally available functions” is reminiscentof the “box” modality in Bahr et al. [1] and Krishnaswami [20], and the F and G construction canbe understood as decomposing the box modality into two separate steps. This relationship will bemade precise in the logical interpretation of λ Widget in section 3As a final example, we will show how to dynamically update the GUI, i.e., how to add newwidgets on the fly. Before we can give the example, we need to extend our widget API, to allowcomposition of widgets. To that end, we add the vAttach command to our API. vAttach : ∀ ( i, j : Id ) , Widget i ⊸ Widget j ⊸ Widget i This command should be understood as an abstract version the div tag in HTML. In the followingexample, we think of the widget as a simple button that when clicked, will create a new button.When any of the buttons gets clicked, a new button gets attached. buttonStack : ∀ i , Widget i ⊸ Widget i buttonStack w = let ( w , c ) = onClick w in let ( x , hi @ x ) = out e in Graulund et al.5 let ( p , w @ x ) = split x w in let w = ( let ( y , w ) = newWidget hi in vAttach w ( buttonStack w )) @ x in join ( p , w )The important step here is in line 6 and 7. Here the new button is attached at the time of themouse click, and buttonStack is called recursively on the newly created button. This sections gives the formal rules, the meta-theory and the logical interpretation of λ Widget . Briefly,the language is an mixed linear-non-linear adjoint calculus in the style of Benton–Wadler [4,3]. Thenon-linear fragment, also called Cartesian in the following, is a minimal simply typed lambdacalculus whereas the linear fragment contains several non-standard judgments used for widgetprogramming.
We have three separate typing judgments: one for indices, one for Cartesian (non-linear) terms,and one for linear terms. These are distinguished by a subscript on the turnstile, i for indices, c forCartesian terms and l for linear terms. These depend on different contexts. The index judgmentdepends only on a index context, whereas the Cartesian and linear judgments depends on both anindex and a linear and/or a Cartesian context. The rules for context formation is given in Figure 1.These are mostly standard except for the dependence on a previously defined context and the factthat the linear context contains variables of the form a : τ A , i.e., temporal variables. The judgment a : τ A is read as “ a has the type A at the timestep τ ”. In the linear setting we will write a : A instead of a : A , i.e., a judgment in the current timestep. Indices: ⊢ i · ⊢ i Θ s dom ( Θ ) σ ∈ { Id , Time }⊢ i Θ, s : σ Cartesian: · ⊢ c Θ ⊢ c Γ x dom ( Γ ) Θ ⊢ c XΘ ⊢ c Γ, x : X Linear: · ⊢ l Θ ⊢ l ∆ x dom ( ∆ ) Θ ⊢ l A Θ ⊢ i τ : Time Θ ⊢ l ∆, a : τ A Fig. 1.
Context Formation
The index judgment describes how to introduce indices. The typing rules are given in Figure 2.The judgment Θ ⊢ i τ : σ contains a single context, Θ , for index variables. There are only two sortsof indices, identifiers and timesteps.The Cartesian judgment describes the Cartesian, or non-linear, fragment. The typing rules aregiven in Figure 3. This is a minimal simply typed lambda calculus with the addition of the G type, djoint Reactive GUI Programming 9 Index Judgments: τ ∈ Time Θ ⊢ i τ : Time
Time ι ∈ Id Θ ⊢ i ι : Id Id i : σ ∈ ΘΘ ⊢ i i : σ Var
Fig. 2.
Index Typing rules
Cartesian Judgments: Θ ; Γ ⊢ c ⋆ : 1 ( -I) ( x : X ) ∈ ΓΘ ; Γ ⊢ c x : X (Var) Θ ; Γ, x : X ⊢ c e : YΘ ; Γ ⊢ c λx.e : X → Y ( → -I) Θ ; Γ ⊢ c e : X → Y Θ ; Γ ⊢ c e : XΘ ; Γ ⊢ c e e : Y ( → -E) Θ ; Γ ; · ⊢ l t : AΘ ; Γ ⊢ c G t : G A ( G -I) Fig. 3.
Cartesian Typing rules used for moving between the linear and Cartesian fragment, and explained further below. Thejudgment Θ ; Γ ⊢ c t : A has two contexts; Θ for indices and Γ for Cartesian variables.The linear fragment is most of the language, and the typing rules are given in Figure 4. Thejudgment is done w.r.t three contexts, Θ for index variables, Γ for Cartesian variables and ∆ forlinear variables. Many of the rules are standard for a linear calculus, except for the presence of theadditional contexts. We will not describe the standard rules any further.The first non-standard rule is for . The introduction and elimination rules follow from thefact that is a non-strong monad. More interesting is the select rule. Here we see the formal rulecorresponding to the informal explanation in section 2. The important thing here is that we cannot use any previously defined linear variable when typing t ′ and t ′ , since we do not actually know when the typing happens. Note, we can see the select rule as a binary version of the let-binding.This could additionally be extended to a n -ary version, but we do not do this in our core calculus.The rules for A @ τ shows how to move between the judgment t : A @ τ and t : τ A . That is, movingfrom knowing in the current timestep that t will have the type A at time τ and knowing at time τ that t has type A . The ( F -I), ( F -E), ( G -I) and ( G -E) rules show the adjoint structure of thelanguage. The ( G -I) rule takes a closed linear term of type A and gives it the Cartesian type G A .Note, because it has no free linear variables, it is safe to duplicate. The ( G -E) rule lets us get an A without needing any linear resources. Conversely, the ( F -I) rule embeds a intuitionistic terminto the linear fragment and the ( F -E) rule binds an intuitionistic variable to let us freely use thevalue. The quantification rules ( ∃ and ∀ ) should also be familiar, except for the additional contexts.The ( Delay ) rule shows what happens when we actually know the timestep. The important partis ∆ ′ = ∆ ↓ τ which means two things. One, all the variables in ∆ are on the form a : τ A , i.e.,judgments at time τ and two, we shift ∆ into the future such that all the variables of ∆ ′ is of theform a : A . The way to understand this is, if all the variables in ∆ are typed at time τ and theconclusion is at time τ , it is enough to “move to” time τ and then type w.r.t that timestep. Finally,we have ( I τ -E) and ( ⊗ τ -E). These allow us to work with linear unit and products at time τ . Theseare added explicitly since they can not be derived by the other rules, and are needed for typingcertain kinds of programs, e.g., see the typing on turnRedOnClick below. Linear Judgments: Θ ; Γ ; a : A ⊢ l a : A (Var) Θ ; Γ ; ∆, a : A ⊢ l t : BΘ ; Γ ; ∆ ⊢ l λa.t : A ⊸ B ( ⊸ -I) Θ ; Γ ; ∆ ⊢ l t : A ⊸ B Θ ; Γ ; ∆ ⊢ l t : AΘ ; Γ ; ∆ , ∆ ⊢ l t t : B ( ⊸ -E) Θ ; Γ ; · ⊢ l hi : I ( I -I) Θ ; Γ ; ∆ ⊢ l t : I Θ ; Γ ; ∆ ⊢ l t : CΘ ; Γ ; ∆ , ∆ ⊢ l let hi = t in t : C ( I -E) Θ ; Γ ; ∆ ⊢ l t : A Θ ; Γ ; ∆ ⊢ l t : BΘ ; Γ ; ∆ , ∆ ⊢ l h t , t i : A ⊗ B ( ⊗ -I) Θ ; Γ ; ∆ ⊢ l t : A ⊗ B Θ ; Γ ; ∆ , a : A, b : B ⊢ l t : CΘ ; Γ ; ∆ , ∆ ⊢ l let ( a, b ) = t in t : C ( ⊗ -E) Θ ; Γ ; ∆ ⊢ l t : AΘ ; Γ ; ∆ ⊢ l evt t : A ( -I) Θ ; Γ ; ∆ ⊢ l t : A Θ ; Γ ; a : A ⊢ l t : BΘ ; ; ∆ ⊢ l let evt a = t in t : B ( -E) Θ ⊢ i τ : Time Θ ; Γ ; ∆ ⊢ l t : τ AΘ ; Γ ; ∆ ⊢ l t @ τ : A @ τ (@-I) Θ ⊢ i t : Time Θ ; Γ ; ∆ ⊢ l t : A @ τ Θ ; Γ ; ∆ , a : τ A ⊢ l t : BΘ ; Γ ; ∆ , ∆ ⊢ l let a @ τ = t in t : B (@-E) Θ ; Γ ⊢ c e : G AΘ ; Γ ; · ⊢ l runG e : A ( G -E) Θ ; Γ ⊢ c e : XΘ ; Γ ; · ⊢ l F e : F x ( F -I) Θ ; Γ ; ∆ ⊢ l t : F X Θ ; Γ, x : X ; ∆ ⊢ l t : BΘ ; Γ ; ∆ , ∆ ⊢ l let F x = t in t : B ( F -E) Θ, i : σ ; Γ ; ∆ ⊢ l t : AΘ ; Γ ; ∆ ⊢ l Λ ( i : σ ) .t : ∀ ( i : σ ) .A ( ∀ -I) Θ ⊢ i s : σ Θ ; Γ ; ∆ ⊢ l t : ∀ ( i : σ ) .AΘ ; Γ ; ∆ ⊢ l t s : { s/i } A ( ∀ -I) Θ ⊢ i s : σ Θ ; Γ ; ∆ ⊢ l t : { s/i } AΘ ; Γ ; ∆ ⊢ l { s, t } : ∃ ( i : σ ) .A ( ∃ -I) Θ ; Γ ; ∆ ⊢ l t : ∃ ( i : σ ) .A Θ, s : σ ; Γ ; ∆ , a : { s/i } A ⊢ l t : BΘ ; Γ ; ∆ , ∆ ⊢ l let unpack { s, a } = t in t : B ( ∃ -E) Θ ; Γ ; ∆ ⊢ l t : AΘ ; Γ ; ∆ ⊢ l t : B Θ ; Γ ; a : A, t : B ⊢ l t ′ : C Θ ; Γ ; b : B, t : A ⊢ l t ′ : CΘ ; Γ ; ∆ , ∆ ⊢ l select ( t as a t ′ | t as b t ′ ) : C (select) Θ ⊢ i τ : Time ∆ ′ = ∆ ↓ τ Θ ; Γ ; ∆ ′ ⊢ l t : AΘ ; Γ ; ∆ ⊢ l t : τ A (delay) Θ ⊢ i τ : Time Θ ; Γ ; ∆ ⊢ l t : τ I Θ ; Γ ; ∆ ⊢ l t : BΘ ; Γ ; ∆ , ∆ ⊢ l let hi @ τ = t in t : B ( I τ -E) Θ ⊢ i τ : Time Θ ; Γ ; ∆ ⊢ l t : τ A ⊗ B Θ ; Γ ; ∆ , a : τ A, b : τ B ⊢ l t : CΘ ; Γ ; ∆ , ∆ ⊢ l let ( a, b ) @ τ = t in t : C ( ⊗ τ -E) Fig. 4.
Linear Typing rulesdjoint Reactive GUI Programming 11
The type system as given above contains both A and A @ k , as two different way to handle time.The former denotes that something of type A will arrive at some point in the future, whereas thelatter denotes that something of type A arrives at a specific point in the future. The strength of is that is gives easy and concise typing rules, whereas the strength of A @ k is that it allows for amore precise usage of time. To connect these two, we add the linear isomorphism A ∼ = ∃ k.A @ k to our language, which is witnessed by out and into , as part of the widget API. This isomorphism istrue semantically, but can not be derived in the type system. In particular, this isomorphism allowsthe select rule to be given with , while still allowing the use timesteps when working with theresulting event. If we were to give the equivalent definition using timesteps, one would need to havesome sort of constraint system for deciding which events happens first. Avoiding such a constraintsystems also allows for a much simpler implementation, as everything is our type system can beinferred. The meta-theory of λ Widget is given in the form of a series of substitution lemmas. Since we havethree different contexts, we will end up with six different substitutions into terms. The Cartesianto Cartesian, Cartesian to linear and linear to linear are the usual notion of mutual recursivesubstitution. More interesting is the substitution of indices into Cartesian and linear terms andtypes. We prove the following lemma, showing that typing is preserved under index substitution:
Lemma 1 (Preservation of Typing under Index Substitution). ζ : Θ ′ → Θ Θ ; Γ ⊢ c e : XΘ ′ ; ζ ( Γ ) ⊢ c ζ ( e ) : ζ ( X ) ζ : Θ ′ → Θ Θ ; Γ ; ∆ ⊢ l t : τ AΘ ′ ; ζ ( Γ ); ζ ( ∆ ) ⊢ l ζ ( t ) : τ ζ ( A )Both are these (and all other cases for substitution) are proved by a lengthy but standard inductionover the typing tree. See the technical appendix for full proofs of all six substitution lemmas. In the following, we go through the formal typing of the turnRedOnClick example from section 2.In the below, we have annotated each line with the contents of the index context (omitting the i : Id that is given upfront) and the linear context. turnRedOnClick : ∀ ( i : Id ) , Widget i ⊸ Widget i turnRedOnClick i w = -- w : Widget i let ( w , c ) = onClick i w in -- w : Widget i, c : I let unpack ( x , c ) = out c in -- x : Time ; w : Widget i, c : I @ x let c @ x = c in -- x : Time ; w : Widget i, c : x I let hi @ x = c in -- x : Time ; w : Widget i let ( p , w ) = split i x w in -- x : Time ; p : Prefix i x, w : Widget i @ x let w @ x = w in -- x : Time ; p : Prefix i x, w : x Widget i let w = ( setColor ( F Red ) w ) @ x in -- x : Time ; p : Prefix i x, w : Widget i @ x join i x ( p , w ) Most of the above is simple application of elimination rules. In line 4, we add the indices variable x : Time to the index context. Note in particular the use of I τ − E in line 6 to discharge c : x I . Thepoint where we actually modify the widget is in line 9 and 10, where we have the following typing: ∆ ⊢ w : x Widget i∆ ⊢ ( setColor ( F Red ) w ) @ x : Widget i @ x ∆ ⊢ p : Prefix i x ∆ ⊢ w : Widget i @ x∆ , ∆ ⊢ join i x ( p, w ) : Widget i∆ , ∆ ⊢ let w = ( setColor ( F Red ) w ) @ x in join i x ( p, w ) : Widget i where ∆ = w : x Widget i, ∆ = p : Prefix i x and ∆ = w : Widget i @ x . Our language has a straightforward logical interpretation.The logic corresponding to the Cartesian fragment is a propositional intuitionistic logic, followingthe usual Curry–Howard interpretation. The logic corresponding to the substructural part of thelanguage is a linear, linear temporal logic. The single-use condition on variables means that thesyntax and typing rules correspond to the rules of intuitionistic linear logic (i.e., the first occurrenceof linear in “linear, linear temporal”). However, we do not have a comonadic exponential modality ! A as a primitive. Instead, we follow the Benton–Wadler approach [4,3] and decompose the exponentialinto the composition of a pair of adjoint functors mediating between the Cartesian and linear logic.In addition to the Benton–Wadler rules, we have a temporal modality A , which corresponds tothe eventually modality of linear temporal logic (i.e., the second occurrence of “linear” in “linear,linear temporal logic”). This connective is usually written F A in temporal logic, but that collideswith the F modality of the Benton–Wadler calculus. Therefore we write it as A to reflect its natureas a possibility modality (or monad). In our calculus, the axioms of S4.3 are derivable:( T ) : A ⊸ A (4) : A ⊸ A ( .
3) : ( A ⊗ B ) ⊸ (( A ⊗ B ) ⊕ ( A ⊗ B ) ⊕ ( A ⊗ B ))Note that because the ambient logic is linear, intuitionistic implication X → Y is replaced withthe linear implication A ⊸ B , and intuitionistic conjunction X ∧ Y is replaced with the linear tensorproduct A ⊗ B . It is easy to see that the first two axiom corresponds to the monadic structure of , and the .3 axiom corresponds to the select rule (with our syntax for select corresponding toimmediately waiting for and then pattern-matching on the sum type). In the literature, the .3axiom is often written in terms of the box modality A [8], but we present it here in a (classically)equivalent formulation mentioning the eventually modality A .We do not need to offer an additional explicit box modality A , since the decomposition of theexponential F ( G A ) from the linear-non-linear calculus serves that role.In our system, we do not want to offer the next-step operator (cid:3) A . Since we want to modelasynchronous programming, we do not want to include a facility for permitting programmers towrite programs which wake up in a specified amount of time. Instead, we only offer an iteratedversion of this connective, A @ n , which can be interpreted as (cid:3) n A , and our term syntax does nothave any numeric constants which can be used to demand a specific delay.Finally, the universal and existential quantifiers (in both the intuitionistic and linear fragments)are the usual quantifier rules for first-order logic. djoint Reactive GUI Programming 13 In this section we will present a denotational model for λ Widget . The model is a linear-non-linear(LNL) hyperdoctrine [24,16] with the non-linear part being
Set and the linear part being the cate-gory of internal relations over a suitable “reactive” category. The hyperdoctrine structure itself isused to interpret the quantification over indices. It many ways this model is entirely standard, andthe most interesting thing is the reactive base category and the interpretation of widgets. It is wellknown that any symmetric monoidal closed category (SMCC) models multiplicative intuitionisticlinear logic (MILL), and it is similarly well known that the category of relations over
Set can begive the structure of a SMCC by using the Cartesian product as both the monoidal product andmonoidal exponential. This construction lift directly to any category of internal relations over acategory that is suitably “
Set -like”, i.e., a topos. Our base category is a simple presheaf category,and hence, we use this construction to model the linear fragment of λ Widget . The base reactive category is where the notion of time will arise and is it this notion that will belifted all the way up to the LNL hyperdoctrine. The simplest model of “time” is
Set N , which can beunderstood as “sets through time” [23]. This can indeed by used as a model for a reactive setting,but for our purposes it is too simple, and further, depending on which ordering is considered for N , may have undesirable properties for the reactive setting. Instead, we use the only slightly morecomplicated Set N +1 , henceforth denoted R , where the ordering on N + 1 is the discrete ordering on N and 1 is related to everything else. Adding this “point at infinity” allows global reasoning aboutobjects, an intuition that is further supported by the definition of the sub-object classifier below.Further, this model is known to be able to differentiate between least and greatest fixpoints [15],and even though we do not use this for λ Widget , we consider it a useful property for further work(see section 5). Objects in R can be visualized as A = A ∞ A A · · · π π We can think of A ∞ as the global view of the object and A n as the local view of the object ateach timestep. Morphisms are natural transformations between such diagrams and the naturalitycondition means that having a map from A ∞ to B ∞ must also come with coherent maps at eachtimestep.In R we define two endofunctors, which can be seen as describing the passage of time: Definition 1.
We define the later and previous endofunctors on R , denoted (cid:3) and (cid:1) , respectively: ( (cid:3) A ) n := n = 0 A n ′ n = n ′ + 1 A ∞ n = ∞ ( (cid:1) A ) n := ( A n +1 n = ∞ A ∞ n = ∞ Note that when we apply the later functor, the global view does not change, but the local viewsare shifted forward in time.
Theorem 1.
The later and previous endofunctors form an adjunction: (cid:1) ⊢ (cid:3) Proof.
The proof follows easily from an examination of the appropriate diagrams.
Definition 2.
The sub-object classifier, denoted Ω , in R is the object P ( N ) + 1 { , } { , } · · · For each n ∈ N , Ω n denotes whether a given proposition is true at the n th timestep. Ω ∞ gives the“global truth” of a given proposition. The left injection is some subset of N that denotes at whichpoints in time something is true. The right injection denotes that something is true “at the limit”,and in particular, also at all timesteps. Note, a proposition can be true at all timesteps but not atthe limit. This extra point at infinity is precisely what allows us the differentiate between least andgreatest fixpoints. To interpret the linear fragment of the language, we will use the category of internal relations on R . Given two objects A and B in R , an internal relation is a sub-object of the product A × B .This can equivalently by understood as a map A × B → Ω . The category of internal relations in thecategory where the objects are the objects of R and the morphisms A → B are internal relations A × B → Ω in R . We denote the category of internal relations as Rel R . Definition 3.
We define a monoidal product and monoidal exponential on
Rel R as A ⊗ B = A × B A ⊸ B = A × B Theorem 2.
Using the above definition of monoidal product and exponential,
Rel R is a symmetricmonoidal closed category.Proof. All of the properties of the monoidal product and exponential follows easily. Consider theevaluation map ( A ⊸ B ) ⊗ A → Rel R B . By definition this is a relation ( A × B ) × A ∼ R B , whichis a map (( A × B ) × A ) × B → R Ω . We define this map to be “true” for tuples ((( a, b ) , a ′ ) , b ′ ) with a = R a ′ ∧ b = R b ′ . Theorem 3.
There is an adjunction in
Rel R : (cid:1) ⊢ (cid:3) where (cid:1) and (cid:3) are the lifting of the previous and later functors from R to Rel R . Definition 4.
We define the iterated later modality or the “at” connective as a successive appli-cation of the later modality. (cid:3) A = A (cid:3) ( k +1) A = (cid:3) ( (cid:3) k A ) and we will alternatively write A @ k to mean (cid:3) k A . djoint Reactive GUI Programming 15 Definition 5.
We define the event functor on
Rel R as an application of the iterated later modality. A : Rel R → Rel R ( A ) ∞ = A ∞ ( A ) n = Σ ( k : N ) . ( (cid:3) k A ) n The event functor additionally carries a monadic structure (see [29] and the technical appendix).
Theorem 4.
We have the following isomorphism for any A A ∼ = Σ ( n : N ) .A @ n Proof.
This follows immediately by the two preceding definitions.
Theorem 5.
We have the following adjunctions between
Set , R and Rel R : Set ⊥ R ⊥
Rel R ∆ I lim P where ∆ is the constant functor, lim is the limit functor, I is the inclusion functor and P is theimage functor. Corollary 1.
The above adjunction induces an adjunction between
Set and
Rel R . One of the most important objects in
Rel R is the widget object. This object will be used to interpretwidgets and prefixes. The widget object will be defined with respect to an ambient notion ofidentifiers, which we will denote Id . These will be part of the hyperdoctrine structure define below,and for now, we will just assume such an object to exists. We will also use a notion of timestepsinternal to the widget object. Note that this timestep is different from the abstract timestep usedfor defining Rel R , but are related as defined below. We denote the abstract timesteps with Time .Before we can define the widget object itself, we need to define an appropriate object of com-mands. In our minimal Widget API, the only semantic commands will be setColor , onClick and onKeypress . The rest of the API will be defined as morphisms on the widget object itself. To workwith the semantics commands, we additionally need a compatibility relation. This relation describeswhat commands can be applied at the same time. In our setting this relation is minimal, but canin principle be used to encode whatever restrictions is needed for a given API. Definition 6.
We define the command object as
Cmd = { ( setColor , color ) , onClick , onKeypress } where color is some element of an “color” object. We define the compatibility relations as cmd ⊲⊳ cmd ′ iff cmd = ( setColor , c ) ⇒ cmd ′ = ( setColor , c ′ ) The only non-compatible combination of commands is two application of the setColor command,the idea being that you can not set the color twice in the same timestep.We can now define the widget and prefix objects
Definition 7.
The widget object, denoted
Widget , is indexed by i ∈ Id and is defined as Widget ∞ i = { ( w, i ) | w ∈ P ( Time × Cmd ) , ( t, c ) ∈ w ∧ ( t, c ′ ) ∈ w → c ⊲⊳ c ′ } Widget n i = { ( w, i ) ⊂ Widget ∞ i | ∀ ( t, c ) ∈ w, t n } The prefix object, denoted
Prefix , is indexed by i ∈ Id and t ∈ Time and is defined as
Prefix ∞ i t = { ( P, i ) ⊂ Widget ∞ i | ∀ ( t ′ , c ) ∈ P, t ′ t } Prefix n i t = ( { ( P, i ) ⊂ Prefix ∞ i t | ∀ ( t ′ , c ) ∈ P, t ′ n } n < t I otherwise The widget object is basically a collection of times and commands keeping track of what hashappened to the widget at various times. One can think of an logbook with entries for each timestep. At the point at infinity, the “global” behavior of the widget is defined, i.e., the full logbook ofthe widget. For each n , Widget n is simply what has happened to the widget so far, i.e., a truncatedlogbook. The prefix object is a widget object that is only defined up to some timestep, and is theunit after that.Observe there is a semantic difference between the widget where the color is set only once, andthe widget where the color is set at every timestep, and this reflects a real difference in actualwidget behavior. The difference between turnRedOnClick w and keepTurningRed w is that if theformer is later set to be blue, it will remain blue, whereas the latter will turn back to being red.To work with widgets we define two “restriction” maps, which are used later for the interpreta-tions. Definition 8.
We define the following on widgets and prefixes shift t : Widget i → Rel R Widget i prefix t i : Widget i → Rel R Prefix i t ( shift t W ) n = { ( t ′ − t, c ) | ( t ′ , c ) ∈ W ∧ t t ′ } ( prefix t i W ) n = ( { ( t ′ , c ) ∈ W | t ′ < t } n < t I n > t The intuition behind these is that prefix t i “cuts off” the widget after t , giving a prefix, whereas shift t shifts forward all entries in the widget by t .Using the above, we can now define the split and join morphisms. These are again given w.r.tambient Id and Time objects, which will be part of the full hyperdoctrine structure:
Definition 9.
We define the following morphisms on the widget object split i t : Widget i → Rel R Prefix i t ⊗ Widget i @ t join i t : Prefix i t ⊗ Widget i @ t → Rel R Widget i ( split i t w ) n = ( prefix t i w, shift t w ) n ( join i t ( p, w )) n = ( p n n < tw n − t n > t djoint Reactive GUI Programming 17 So far we have not explained in details how to model the quantifiers in our system. To do this,we use the notion of a hyperdoctrine [22]. For ordinary first-order logic, this is a functor from acategory of contexts and substitutions to the category of Cartesian closed categories, with the ideabeing that we have one CCC for each valuation of the free first-order variables.As our category of contexts, we use a Cartesian category that can interpret our index objects,namely
Time and Id , where the former is interpreted as N + 1 and the latter as N . In our case, both Set and
Rel R are themselves hyperdoctrines w.r.t to this category of contexts, the former a first-order hyperdoctrine and the latter a multiplicative intuitionistic linear logic (MILL) hyperdoctrine.Together these form a linear-non-linear hyperdoctrine through the adjunction given in Corollary 1.Formally, we have Definition 10.
A linear-non-linear hyperdoctrine is a MILL hyperdoctrine L together with a first-order hyperdoctrine C and a fiber-wise monoidal adjunction F : L ⇆ C : G . Theorem 6.
The categories
Set and
Rel R form a linear-non-linear hyperdoctrine w.r.t the inter-pretation of the indices objects, with the adjunction given as in Corollary 1. We refer the reader to the accompanying technical appendix for the full details.
We the above, we have enough structure to give an interpretation of λ Widget . Again, most of this in-terpretation is standard in the use of the hyperdoctrine structure, and we interpret in the obviousway using the linear hyperdoctrine structure on Rel R . As an example, we sketch the interpretationof the widget object and the setColor command below. Definition 11.
We interpret the
Widget i and Prefix i types using the widget and prefix objects: J Θ ⊢ Widget i K = Widget J Θ ⊢ s i : Id KJ Θ ⊢ Prefix i t K = Prefix J Θ ⊢ s i : Id K J Θ ⊢ s t : Time K and we interpret the setColor commands as: J setColor : ∀ ( i : Id ) , Widget i ⊗ F Color ⊸ Widget i K = { w ∪ W { (0 , ( setColor , col )) } | w ∈ J Widget i K , col ∈ J Color K } where ∪ W is a “widget union”, which is a union of sets such that identifiers indices and compatibilityof commands are respected This interpretation shows that a widget is indeed a logbook of events. Using the setColor commandsimply adds an entry to the logbook of the widget. Note we only set the color in the current timestep.To set the color in the future, we combine the above with appropriate uses of splits and joins. Theinterpretation of split and join are done using their semantic counterparts, and the interpretationof onClick and onKeypress are done, using our non-deterministic semantics, by associating a widgetwith all possible occurrences of the corresponds event.
Finally, we prove that semantic substitution is sound w.r.t syntactic substitution. As with theproofs of type preservation for syntactic substitution, there are several cases for the different kindsof substitution, but the main results is again concerned with substitution of indices:
Theorem 7.
Given ζ : Θ ′ → Θ , Θ ; Γ ⊢ c e : X and Θ ; Γ ; ∆ ⊢ l t : A then J ζ K J Θ ; Γ ⊢ c e : X K = J Θ ′ ; ζ ( Γ ) ⊢ c ζ ( e ) : ζ ( X ) KJ ζ K J Θ ; Γ ; ∆ ⊢ l t : A K = J Θ ′ ; ζ ( Γ ); ζ ( ∆ ) ⊢ l ζ ( t ) : ζ ( A ) K Proofs for all six substitutions lemmas can be found in the technical appendix.
Much work has sought to offer a logical perspective on FRP via the Curry–Howard correspon-dence [21,18,17,19,20,10,1]. As mentioned earlier, most of this work has focused on calculi that havea Nakano-style later modality [25], but this has the consequence that it makes it easy to writeprograms which wake up on every clock tick.In this paper, we remove the explicit next-step modality from the calculus, which opens the doorto a more efficient implementation style based on the so-called “push” (or event/notification-based)implementation style. Elliott [12] also looked at implementing a push-based model, but viewed itas an optimization rather than a first-class feature in its own right. We also hope to use an effectsystem to track when reflows and redraws occur, which should make it easier to keep track of whenpotentially expensive UI operations are taking place. Moreover, we can extend the widget semanticsand compatibility relation to track these events, which should let us test if we can easily put thedomain knowledge of browser developers into our semantic model.In future work, we plan on implementing a language based upon this calculus, with the ideathat we can compile to Javascript, and represent widgets with DOM nodes, and represent the A and A @ n temporal connectives using doubly-negated callback types (in Haskell notation, EventA = (A -> IO ()) -> IO () ). This should let us write GUI programs in a convenient functionalstyle, while generating code which attaches callbacks and does mutable updates in the same stylethat a handwritten GUI program would use.Our model, in terms of
Set N +1 , can be seen as a model of LTL that has been enriched frombeing about time-indexed true-values to time-indexed sets. The addition of the global view orpoint at infinity has the benefit that it enables us to give a model that distinguishes between leastand greatest fixed points [15] (i.e., inductive and coinductive types), unlike in models of guardedrecursion where guarded types are bilimit-compact [6]. This will let us use the idea that temporalliveness and safety properties can be encoded in types using inductive and coinductive types [10,2].One interesting recent development in natural deduction systems for comonadic modalities is theintroduction of the so-called “Fitch-style” calculi [7,11], which offer an alternative to the Pfenning–Davies pattern-style elimination [26] for the box comonad. These calculi have seen successful appli-cation to reactive programming languages [1], and one interesting question is whether they extendto Benton–Wadler adjoint calculi as well – i.e., can the F ( X ) modality be equipped with a directstyle eliminator? djoint Reactive GUI Programming 19 References
1. Bahr, P., Graulund, C.U., Møgelberg, R.E.: Simply RaTT: a Fitch-style modal calculus for reactiveprogramming without space leaks. Proceedings of the ACM on Programming Languages (ICFP), 1–27(2019)2. Bahr, P., Graulund, C.U., Møgelberg, R.: Diamonds are not forever: Liveness in reactive programmingwith guarded recursion (2020)3. Benton, N., Wadler, P.: Linear logic, monads and the lambda calculus. Proceedings 11th Annual IEEESymposium on Logic in Computer Science pp. 420–431 (1996)4. Benton, P.N.: A mixed linear and non-linear logic: Proofs, terms and models. In: Pacholski, L., Tiuryn,J. (eds.) Computer Science Logic. pp. 121–135. Springer Berlin Heidelberg, Berlin, Heidelberg (1995)5. Berry, G., Cosserat, L.: The ESTEREL synchronous programming language and its mathematicalsemantics. In: Brookes, S.D., Roscoe, A.W., Winskel, G. (eds.) Seminar on Concurrency. pp. 389–448.Springer Berlin Heidelberg, Berlin, Heidelberg (1985)6. Birkedal, L., Møgelberg, R.E., Schwinghammer, J., Støvring, K.: First steps in synthetic guarded domaintheory: Step-indexing in the topos of trees. In: In Proc. of LICS (2011)7. Bizjak, A., Grathwohl, H.B., Clouston, R., Møgelberg, R.E., Birkedal, L.: Guarded dependent typetheory with coinductive types. In: International Conference on Foundations of Software Science andComputation Structures. pp. 20–35. Springer (2016)8. Blackburn, P., de Rijke, M., Venema, Y.: Modal Logic. Cambridge Tracts in Theoretical ComputerScience, Cambridge University Press (2002)9. Caspi, P., Pilaud, D., Halbwachs, N., Plaice, J.A.: LUSTRE: A Declarative Language for Real-time Programming. In: Proceedings of the 14th ACM SIGACT-SIGPLAN Symposium on Prin-ciples of Programming Languages. pp. 178–188. POPL ’87, ACM, New York, NY, USA (1987).https://doi.org/10.1145/41625.4164110. Cave, A., Ferreira, F., Panangaden, P., Pientka, B.: Fair Reactive Programming. In: Proceedings ofthe 41st ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages. pp. 361–372.POPL ’14, ACM, San Diego, California, USA (2014). https://doi.org/10.1145/2535838.253588111. Clouston, R.: Fitch-style modal lambda calculi. In: Baier, C., Dal Lago, U. (eds.) Foundations ofSoftware Science and Computation Structures. pp. 258–275. Springer International Publishing, Cham(2018)12. Elliott, C.: Push-pull functional reactive programming. In: Haskell Symposium (2009),http://conal.net/papers/push-pull-frp13. Elliott, C., Hudak, P.: Functional reactive animation. In: Proceedings of the Second ACM SIGPLANInternational Conference on Functional Programming. pp. 263–273. ICFP ’97, ACM, New York, NY,USA (1997). https://doi.org/10.1145/258948.25897314. Girard, J.Y.: Linear logic. Theoretical Computer Science (1), 1 – 101 (1987).https://doi.org/10.1016/0304-3975(87)90045-415. Graulund, C.: Lambda Calculus for Reactive Programming. Master’s thesis, IT University of Copen-hagen (2018)16. Haim, M., Malherbe, O.: Linear Hyperdoctrines and Comodules. arXiv e-prints arXiv:1612.06602 (Dec2016)17. Jeffrey, A.: LTL types FRP: linear-time temporal logic propositions as types, proofs as functionalreactive programs. In: Proceedings of the sixth workshop on Programming Languages meets ProgramVerification, PLPV 2012, Philadelphia, PA, USA, January 24, 2012. pp. 49–60. Philadelphia, PA, USA(2012). https://doi.org/10.1145/2103776.210378318. Jeltsch, W.: Towards a common categorical semantics for linear-time temporal logic and functionalreactive programming. Electronic Notes in Theoretical Computer Science , 229–242 (2012)19. Jeltsch, W.: Temporal Logic with ”Until”, Functional Reactive Programming with Processes,and Concrete Process Categories. In: Proceedings of the 7th Workshop on Programming Lan-guages Meets Program Verification. pp. 69–78. PLPV ’13, ACM, New York, NY, USA (2013).https://doi.org/10.1145/2428116.24281280 Graulund et al.20. Krishnaswami, N.R.: Higher-order Functional Reactive Programming Without SpacetimeLeaks. In: Proceedings of the 18th ACM SIGPLAN International Conference on Func-tional Programming. pp. 221–232. ICFP ’13, ACM, Boston, Massachusetts, USA (2013).https://doi.org/10.1145/2500365.250058821. Krishnaswami, N.R., Benton, N.: Ultrametric semantics of reactive programs. In: 2011 IEEE 26thAnnual Symposium on Logic in Computer Science. pp. 257–266. IEEE Computer Society, Washington,DC, USA (June 2011). https://doi.org/10.1109/LICS.2011.3822. Lawvere, F.W.: Adjointness in foundations. Dialectica (3-4), 281–296 (1969).https://doi.org/10.1111/j.1746-8361.1969.tb01194.x23. MacLane, S., Moerdijk, I.: Sheaves in Geometry and Logic: A First Introduction to Topos Theory.Universitext, Springer New York (1994). https://doi.org/10.1007/978-1-4612-0927-024. Maietti, M.E., de Paiva, V., Ritter, E.: Categorical models for intuitionistic and linear type theory. In:Tiuryn, J. (ed.) Foundations of Software Science and Computation Structures. pp. 223–237. SpringerBerlin Heidelberg, Berlin, Heidelberg (2000)25. Nakano, H.: A modality for recursion. In: Proceedings Fifteenth Annual IEEE Symposium on Logic inComputer Science (Cat. No.99CB36332). pp. 255–266. IEEE Computer Society, Washington, DC, USA(June 2000). https://doi.org/10.1109/LICS.2000.85577426. Pfenning, F., Davies, R.: A judgmental reconstruction of modal logic. Mathematical Structures inComputer Science11