Event sourcing using functional programming
The key concept in event sourcing is having an 'updater' function that takes an event and an old state, and returns a new state. Let's capture that as a type. The type can be very generic:

module Update =
  type t&lt;'s, 'e&gt; = 's -&gt; 'e -&gt; 's

  (**
  A function that represents the operation of taking an event and an old
  state to return a new state.
  *)


The next thing to capture is your specific domain and its specific implementation of the 'updater' function:

module Account =
  type t = { logged_in : bool; balance : decimal }
  type event =
    | Login of userid:string * passwd:string
    | Deposit of decimal
    | Withdraw of decimal

  let empty = { logged_in = false; balance = 0m }
  let login_valid userid passwd = true // &lt;- TBD
  let update t event =
    match event, t with
      | Login (userid, passwd), _ -&gt;
        { t with logged_in = login_valid userid passwd }

      | Deposit amt, { logged_in = true; balance = balance } -&gt;
        { t with balance = balance + amt }

      | Withdraw amt, { logged_in = true; balance = balance } -&gt;
        { t with balance = balance - amt }

      | _, t -&gt; t

  (* val update : Update.t&lt;t, event&gt;


Finally, you need some stream of events. It can be in the form of some stream data type or an observable sequence. We will use an IObservable&lt;Account.event&gt; because it's idiomatic in the .Net world. With this stream of events, you can 'fold' over the events and regenerate your final state (your account) by applying the update function at each step.

module Main =
  open System.Reactive.Linq

  (* For example only; real stream will be built differently. *)
  let acct_events =
    Observable.Concat(
      [| Observable.Return(Account.Login ("bob", "pass"))
         Observable.Return(Account.Deposit 1000m)
         Observable.Return(Account.Withdraw 500m) |])

  let acct =
    Observable.Aggregate(acct_events, Account.empty, Account.update)

  (** val acct : IObservable&lt;Account.t&gt; *)