So in this session, we are going to look at a different take of event handling programs. A functional view of events that's embodied in functional reactive programming. You have seen that reactive programming is all about reacting to some sequences of events that happen in time. The functional view is that we can actually take such a sequence of events and aggregate it into a signal. So, a signal is a value that changes over time and it's represented as a function from the time domain to the value domain. That means that instead of propagating updates to a mutable state one by one, we define new signals in terms of existing ones. In a signal operation, we can define a new signal in terms of signals that we have already defined. So let's make this concrete with an example. Let's say we want to track mouse positions, or here we'll substitute the mouse with my pen. When the user moves the mouse, usually a sequence of events is fired. Each time the mouse is at a new position, the application gets a MouseMoved event with the current position of the mouse. And it would have to handle that event by updating its internal state and all these updates would typically be imperative. How can I lift this into a functional viewpoint? So the core idea is that I define a signal, call it also mouse position, which is now a signal of position. Which, at any point in time, represents the current mouse position. So it's a function from the domain of time values to this curve. At the initial time value, the position was here and then it would go progressively until at the final time value, the position was here. That gives me a function from time values to positions. Functional reactive programming started in 1997, with the Paper Functional Reactive Animation by Conal Elliott and Paul Hudak. And Conal also wrote a language called Fran, which was implemented as an embedded library in Haskell. There have been quite a few FRP systems since. Both standalone languages and embedded libraries. The list is too long to give you a complete picture, so I'll just give you some examples. Flapjax is one, Elm, Bacon.js, both target JavaScript. React4j is a Java library that has a minimal reactive programming framework. Related, but not quite the same, are the event streaming dataflow programing systems such as Rx. In fact, we will see Rx more in two weeks. They are related to FRP, but commonly the FRP, in the strict sense, is not used for this. We will introduce FRP not with one of the existing frameworks, but with a really minimal class, which we will define ourselves. Which we call frp.Signal. And we'll explain the implementation of frp.Signal at the end of the next module. frp.Signal is modeled after the library Scala.react, which is described in the paper Deprecating the Observer Pattern by Ingo Maier and myself. And in fact, the React4J libraries also influenced by this Scala.react library. So it has abstractions that are a bit similar to what we are going to see here. So let's have a closer look at signals. There are two fundamental operations over signal. First, I can obtain the value of a signal at the current time. In our FRP signal library, that's expressed by applying the signal to an empty parameter list. So mouse position, open parenths, closed parenths, would give us the mouse position at the current time. The second fundamental operation is to define a signal in terms of other signals. In our library, that's expressed by the signal constructor. So let's do an example. Let's say I have drawn my curve. And I have given a rectangle. Like this. And I want to define a new signal which is either true or false, depending on whether the curve or the mouse was in the rectangle or not. So that new signal would look something like this, would start with false, and then at this point in time, it would jump to true. And it would stay true for a while and it would go back to false. So that's false. That's true. So it's a discrete signal with two states. Here's how I would define it. I would define the signal inRectangle, which takes as parameters, the coordinates of the rectangle, given as a lower left corner and an upper right corner. And it's defined by this expression here. So what that says is that at each point in time, I return the signal that looks at the mouse position at the same point in time, at the current point in time, and returns whether that position is between the lower left and the upper right corners. So we've seen the signal syntax to define the rectangle signal in terms of the mouse position signal. But it can also be used to define a signal that has no dependencies and always defines the same value. So for instance, signal 3 would define the signal that was constant 3, that was always the number 3. So we've seen constant signals, but how do we define a signal that varies in time? Well, we've seen already some of these varying signals are defined externally, something like mouse position that the system could give us. We can also map over the externally defined signals that vary in time and that gives us new signals that vary in time. Or the other way is that we can use a Var. A Var is a subclass of signal that we are going to see next. So far, all values of type signal are immutable. A signal is an immutable function from time to the signal values. But in fact our library also defines a subclass Var of signals for signals that can be changed. The change system, by means of an update operation, which Var provides. And that update operation allows to redefine the value of a Var signal from the current time on. So if we look at this example here, it defines sig to be a var(3). So that's a signal that, for now, is always the constant 3 until the point where I define an update operation on that signal. From that point on, it will always be 5. Until, of course, there is the next update operation maybe happening in the future. So the update operation uses the name update for a reason. Because, in fact, in Scala, update calls can be rewritten as assignments using some syntactic sugar. You've probably seen that already when working with arrays. For an array arr, you would write arr(i) = 0. And what actually happens here is that this expression that this assignment is translated to arr.update i and 0. And that would call the update method in class array, which has this definition here. So update takes an index and a value of the element type of the array and returns unit. So under the covers when you write an index assignment like that, you really get a call to update. Generally, an index assignment like f(E1 to En) = E is translated by the Scala compiler to f.update (E1, En, E). And that works, not just for arrays, but for all types that define and update method of the right array team. And that also works if n = 0. So if there are no indexes, that means that we f() = E is a shorthand for f.update(E). So since we have such an update method on signal. It means that sig.update(5), a call like that, can be abbreviated to simply sig() = 5. You'll probably notice that signals of type var look a bit like mutable variables, where sig() is dereferencing, reading the variable. And sig() = newValue is writing the variable or update. But there's a crucial difference. We can map over signals, which gives us a relation between two signals that is maintained automatically, at all future points in time. Whereas, for variables, no such mechanisms exist. We have to update all variables manually whenever some dependant variable changes. So, for instance, if we have a variable a initialized to 2, and then b would be 2 x a, and then we would update a = a + 1. And the value of b does not automatically get updated together with the value of a, so b would still be 4 even after that assignment. We'd have to update it manually to say, well, b is now again 2 times a, so that would give it 6. Whereas if we did the same thing with signals, it would look like this, so we would have signal a, which is assumed to be a var signal, constant 2. The signal b is assumed to be 2 x a and that assignment would established already essentially the relationship between the b and a forever in the future. So if now a is defined to be 3, then the signal b would be automatically updated to 6. We are going to repeat the bank account example we've seen in the last section with signals. We will add a signal called balance to BankAccounts and we will define a function consolidated which produces the sum of all balances of a given list of accounts. So I have on the screen my class BankAccount from essentially the original example, without any event handling. Deposit and withdrawal method and this variable balance. How do we make this into a source of an FRP signal? Well, one approach would be to say, well, let's make balance a signal, so it would be a val, and that would be a Var(0). So, balance is still a variable, but now it's a signal. So now we say, well, the deposit method would update that signal. Let's just write it like this for now. And the withdraw method would test the signal. And, again, update it like this. So that's how a Straw Man for a bank account with signals. That was easy, right? We just changed the var balance into a variable signal and brought everything over. So let's test that with the worksheet. I have written a worksheet accounts and I've given already the header of a function consolidated which should return the sum of all of the balances of the accounts in this list here. So the type of consolidated would be, then, a Signal(Int). And its definition would be, we define a signal and the signal is defined by means of mapping over all our accounts. For each one we take the balance, And we take the sum of the whole thing. And, of course, we have to take the balance at the current time, so it would be written like this. So that gives us the function consolidated. What we do now is we defined as before, a number of bank accounts. And we want to find out the total balance in consolidated, so the value of consolidated at the current time. All right, so we get 0 as expected. Let's deposit some amount in a and try again. Oops, we got an assertion error. So what does it read here, it says, cyclic, let me just bring that up, cyclic signal definition, that's what it says. So what have we done wrong? So it must be in the bank account. Let's bring that bank account up again. So in fact the error appeared at this line here. And if you look at this line, then you must conclude that indeed it makes no sense whatsoever. What we've done here is to say, well, the signal balance, which is a function over time, is the same as itself plus amount where amount is greater than 0. So, obviously, an equation like that has no solution, you can't define a function that at each point in time is the value of the function itself plus amount. So, that didn't work. And in fact, the system has called us out by throwing an assertion which says there was a cyclic signal definition. We have defined balance in terms of itself. So, how do we fix it? Well, what we need to do to fix it, is we have to pull out the balance signal into, A separate definition here that pulls out the current value of balance and then just does this thing here. And we do the same thing here. So, val b = balance(), and balance() = b + amount. So, how is that different? Well, what we do now is to say we type the current value of balance, call it b, and then define the new balance after that to be that value plus amount. So what we do now is not define a cyclic definition, not to have a cyclic definition. But indeed define a constant function which will return, at all points in future, the value of this expression here. So you see that the interaction of state and functions is very subtle as we have observed at several points before. It makes an obvious difference, but the balance here is defined as right inside of a signal definition or pulled out into its own var. Let's redo the worksheet with that example. And, in fact, now we get the correct result. The a deposit is 20. Let's deposit as before, 30 in b. Call it again, and that would give us this here. Let's go a little bit further and, say, we want to have another signal which defines an exchange rate. Let's just call, Let's say the exchange rate is first 246 let's say dollars for bitcoins. And let's say our value, our total sum is in dollars is then what we had before Signal that, take c times the signal exchange rate. Now we would have a different signal inDollar, which has this value here. Now if changed let's say b again, b withdraw 10, and look at the result inDollar, and you'll see that the deduction in b is reflected in our inDollar result. First the signal c got updated and then the signal inDollar got updated as well. So that was the bank account example redone with signals instead of subscribers. If you compare to the two solutions then you will notice that the solution with signals is much shorter and you could also argue much cleaner because there is much less data updates than the observer solution which is inherently imperative. We've also seen in the example that there is an important difference between a variable assignment such as this one here and a signal update such as the one that you see here. In the first case, in that variable assignment, the new value of v is the old value of v plus one. So implicitly there's a notion of old value versus new values. When you update a signal, there's no such notion. So what you are trying to say here is that in fact that the signal s is the same as the signal s plus one, which obviously makes no sense. So here's an exercise for you. Consider those two code fragments. The first one says num = Var(1). And we have a signal that is num() * 2. And then we update num() to be 2. And the second one is quite similar. So, we start with a var num equals Var(1). The signal twice is as before. But finally, we define num to be equal Var(2). Are those two code fragments equivalent? That means would they yield the same final value for twice()? So if I evaluate twice here and I evaluate twice here, would I get the same value, yes or no? So let's visualize how these two code fragments behave. In the first case, I have the num signal which is constant 1. And the twice signal which is constant 2. Then at some point I change num to 2 and twice will consequently jump to 4. So that's the update of the first code fragment. Let's have a look at the second one. So again, I have num = Var(1). And twice. Is 2. But what I do now is I define a new signal num, and assign it to the variable. So after this point here num in fact points to a new signal that has the value 2. Whereas the twice signal in fact would still depend on this signal here that I have created up here. So it would stay 2 forever. So while I have here 2 is the final value, inthe first code fragment it was 4. And the two fragments are, indeed, different. It just shows a little bit the subtlety that you have with signal uptake versus variables. Gives you another aspect of that same difference.