# F Sharp Programming/Events

Events allow objects to communicate with one another through a kind of synchronous message passing. Events are simply hooks to other functions: objects register callback functions to an event, and these callbacks will be executed when (and if) the event is triggered by some object.
For example, let's say we have a clickable button which exposed an event called Click. We can register a block of code, something like fun -> printfn "I've been clicked!", to the button's click event. When the click event is triggered, it will execute the block of code we've registered. If we wanted to, we could register an indefinite number of callback functions to the click event—the button doesn't care what code is trigged by the callbacks or how many callback functions are registered to its click event, it blindly executes whatever functions are hooked to its click event.
Event-driven programming is natural in GUI code, as GUIs tend to consist of controls which react and respond to user input. Events are, of course, useful in non-GUI applications as well. For example, if we have an object with mutable properties, we may want to notify another object when those properties change.

## Defining Events

Events are created and used through F#'s Event class. To create an event, use the Event constructor as follows:
To allow listeners to hook onto our event, we need to expose the nameChanged field as a public member using the event's Publish property:
Now, any object can listen to the changes on the person method. By convention and Microsoft's recommendation, events are usually named Verb or VerbPhrase, as well as adding tenses like Verbed and Verbing to indicate post- and pre-events.

## Adding Callbacks to Event Handlers

Its very easy to add callbacks to event handlers. Each event handler has the type IEvent<'T> which exposes several methods:
val Add : event:('T -> unit) -> unit
    Connect a listener function to the event. The listener will be invoked when the event is fired.
val AddHandler : 'del -> unit
    Connect a handler delegate object to the event. A handler can be later removed using RemoveHandler. The listener will be invoked when the event is fired.
val RemoveHandler : 'del -> unit
    Remove a listener delegate from an event listener store.
Here's an example program:
This program outputs the following:
    Note: When multiple callbacks are connected to a single event, they are executed in the order they are added. However, in practice, you should not write code with the expectation that events will trigger in a particular order, as doing so can introduce complex dependencies between functions. Event-driven programming is often non-deterministic and fundamentally stateful, which can occasionally be at odds with the spirit of functional programming. Its best to write callback functions which do not modify state, and do not depend on the invocation of any prior events.

## Working with EventHandlers Explicitly
### Adding and Removing Event Handlers

The code above demonstrates how to use the IEvent<'T>.add method. However, occasionally we need to remove callbacks. To do so, we need to work with the IEvent<'T>.AddHandler and IEvent<'T>.RemoveHandler methods, as well as .NET's built-in System.Delegate type.
The function person.NameChanged.AddHandler has the type val AddHandler : Handler<'T> -> unit, where Handler<'T> inherits from System.Delegate. We can create an instance of Handler as follows:
This program outputs the following:

### Defining New Delegate Types

F#'s event handling model is a little different from the rest of .NET. If we want to expose F# events to different languages like C# or VB.NET, we can define a custom delegate type which compiles to a .NET delegate using the delegate keyword, for example:
The convention obj * NameChangingEventArgs corresponds to the .NET naming guidelines which recommend that all events have the type val eventName : (sender : obj * e : #EventArgs) -> unit.

### Use existing .NET WPF Event and Delegate Types

Try using existing .NET WPF Event and Delegate, example, ClickEvent and RoutedEventHandler. Create F# Windows Application .NET project with referring these libraries (PresentationCore PresentationFramework System.Xaml WindowsBase). The program will display a button in a window. Clicking the button will display the button's content as string.

## Passing State To Callbacks

Events can pass state to callbacks with minimal effort. Here is a simple program which reads a file in blocks of characters:
This program has the following types:
Since our event has the type IEvent<int>, we can pass int data as state to listening callbacks. This program outputs the following:

## Retrieving State from Callers

A common idiom in event-driven programming is pre- and post-event handling, as well as the ability to cancel events. Cancellation requires two-way communication between an event handler and a listener, which we can easily accomplish through the use of ref cells or mutable members:
This program has the following types:
This program outputs the following:
If we need to pass a significant amount of state to listeners, then its recommended to wrap the state in an object as follows:
By convention, custom event parameters should inherit from System.EventArgs, and should have the suffix EventArgs.

## Using the Event Module

F# allows users to pass event handlers around as first-class values in fundamentally the same way as all other functions. The Event module has a variety of functions for working with event handlers:
val choose : ('T -> 'U option) -> IEvent<'del,'T> -> IEvent<'U> (requires delegate and 'del :> Delegate)
    Return a new event which fires on a selection of messages from the original event. The selection function takes an original message to an optional new message.
val filter : ('T -> bool) -> IEvent<'del,'T> -> IEvent<'T> (requires delegate and 'del :> Delegate)
    Return a new event that listens to the original event and triggers the resulting event only when the argument to the event passes the given function.
val listen : ('T -> unit) -> IEvent<'del,'T> -> unit (requires delegate and 'del :> Delegate)
    Run the given function each time the given event is triggered.
val map : ('T -> 'U) -> IEvent<'del,'T> -> IEvent<'U> (requires delegate and 'del :> Delegate)
    Return a new event which fires on a selection of messages from the original event. The selection function takes an original message to an optional new message.
val merge : IEvent<'del1,'T> -> IEvent<'del2,'T> -> IEvent<'T> (requires delegate and 'del1 :> Delegate and delegate and 'del2 :> Delegate)
    Fire the output event when either of the input events fire.
val pairwise : IEvent<'del,'T> -> IEvent<'T * 'T> (requires delegate and 'del :> Delegate)
    Return a new event that triggers on the second and subsequent triggerings of the input event. The Nth triggering of the input event passes the arguments from the N-1th and Nth triggering as a pair. The argument passed to the N-1th triggering is held in hidden internal state until the Nth triggering occurs. You should ensure that the contents of the values being sent down the event are not mutable. Note that many EventArgs types are mutable, e.g. MouseEventArgs, and each firing of an event using this argument type may reuse the same physical argument object with different values. In this case you should extract the necessary information from the argument before using this combinator.
val partition : ('T -> bool) -> IEvent<'del,'T> -> IEvent<'T> * IEvent<'T> (requires delegate and 'del :> Delegate
    Return a new event that listens to the original event and triggers the first resulting event if the application of the predicate to the event arguments returned true, and the second event if it returned false.
val scan : ('U -> 'T -> 'U) -> 'U -> IEvent<'del,'T> -> IEvent<'U> (requires delegate and 'del :> Delegate)
    Return a new event consisting of the results of applying the given accumulating function to successive values triggered on the input event. An item of internal state records the current value of the state parameter. The internal state is not locked during the execution of the accumulation function, so care should be taken that the input IEvent not triggered by multiple threads simultaneously.
val split : ('T -> Choice<'U1,'U2>) -> IEvent<'del,'T> -> IEvent<'U1> * IEvent<'U2> (requires delegate and 'del :> Delegate)
    Return a new event that listens to the original event and triggers the first resulting event if the application of the function to the event arguments returned a Choice2Of1, and the second event if it returns a Choice2Of2.
Take the following snippet:
We can rewrite this in a more functional style as follows: