Author Archives: shane

Experimenting with Partial Application

Partial application helps us reuse functions by allowing us to create new functions based on the original. This is achieved by passing fewer arguments to the original function and binding the new function that is created. You can read more on this at Currying and Applying Arguments. We’re going to experiment with partial application and understand when execution happens.

Short notes: currying is responsible for taking a function with multiple parameters and turning it into a sequence of functions where each function only takes one argument. Partial Application is the process of applying arguments to unwrap the layers of functions until there are no more functions only the result.

Our Test Code

We’re going to start with a simple key lookup. We’ll have a function which takes a list of integers and another integer to verify it is in the list of keys. We’ve created some sample data for testing our functions.

let datapoints = [1 .. 400000]
let keys = [1; -4; 45000; 2501; 56000]

// seq -> int -> bool
let seekKey keys key =
    printfn "Creating index"
    let index = Set.ofSeq keys
    printfn "Seeking key: %d" key
    index |> Seq.contains key

Looking at our starting code, we are taking in a sequence of keys and turning them into a Set. We then look in the set of keys for verification of the key we are looking for. We’ve added some print statements so we can see the execution.

Let’s turn #time on in our REPL to give us some statistics of execution.

When we execute the function with the data points and a key we should see results similar to this:

> seekKey datapoints 67;;

Creating index
Seeking key: 67
Real: 00:00:00.653, CPU: 00:00:00.650 ...

// Your times will differ.

These are the results we expected. We are creating an index, using a Set, and searching the index. Next we’ll create a partially applied function so we can do multiple lookups.

> let seek = seekKey dataPoints;;

Real: 00:00:00.000, CPU: 00:00:00.000 ...

Again the results aren’t to shocking here. We are unwrapping the first layer of currying to reveal the function below. Now let’s use our partially applied function seek to verify a list of keys.

> keys |> List.map (seekKey datapoints);;

Creating index
Seeking key: 1
Creating index
Seeking key: -4
Creating index
Seeking key: 45000
Creating index
Seeking key: 2501
Creating index
Seeking key: 56000
Real: 00:00:03.396, CPU: 00:00:03.512 ...

We’ve revealed a problem with our function. We are creating the index on every lookup. The reason for creating an index is to improve the performance for multiple lookups. We have not accomplished this.

Multiple Seek Improvement

Let’s rewrite our function. Instead of relying on currying, we’ll have our function return a function. This will allow us to inject some execution before performing the lookup.

// seq -> (int -> int)
let seekKey' keys = 
    printfn "Creating index"
    let index = Set.ofSeq keys
    (fun key -> 
        printfn "Seeking key: %d" key
        index |> Seq.contains key)

> seekKey' datapoints 67;;

Creating index
Seeking key: 67
Real: 00:00:00.659, CPU: 00:00:00.656 ...

The type signature of the new function is close to the original function. In fact, we can call the new function the exact same way as the original.

Look at what happens when we apply only the first argument.

> let seek' = seekKey' datapoints;;

Creating index
Real: 00:00:00.690, CPU: 00:00:00.737 ...

We can see the index is created immediately. How is this going to affect multiple key lookups?

> keys |> List.map (seekKey' datapoints);;

Creating index
Seeking key: 1
Seeking key: -4
Seeking key: 45000
Seeking key: 2501
Seeking key: 56000
Real: 00:00:00.710, CPU: 00:00:00.705

That’s a more performant lookup for multiple values. What we’ve done is made the creation of the index happen after applying the first argument. The index then gets wrapped in a closure to the returned function. This means we don’t have to re-create the index every time we apply the second argument.

What more can we do?

We’re close to how we want the function to work. There’s one last thing. It would be nice to create the index only if we use it. We can accomplish this using a lazy computation.

// seq -> (int -> int)
let seekKey'' keys =
    let index = lazy (
                  printfn "Creating index"
                  Set.ofSeq keys)
    (fun key ->
        printfn "Seeking key: %d" key
        index.Value |> Seq.contains key)

We’ve placed the index creation in the lazy expression and bind it to the label index. We then call index.Value when we want to use the result of the lazy computation.

Let’s run through our testing scenarios.

> seekKey'' datapoints 67;;

Seeking key: 67
Creating index
Real: 00:00:00.679, CPU: 00:00:00.732 ...

This revealed an interesting result. The times are fairly equivalent to the first two code snippets, but in this case the print statements are in a different order. We are printing the “Seeking” before the “Creating”. This is due to the lazy and not evaluating until we tell it to.

Applying one argument:

> let seek'' = seekKey'' datapoint;;

Real: 00:00:00.000, CPU: 00:00:00.000 ...

Yes! This is what we wanted. Immediate return of the function without creating the index. This allows us to apply the first argument without any penalty if we don’t use the returned function later in processing.

For completeness, running multiple lookups.

> keys |> List.map (seekKey' datapoints);;

Seeking key: 1
Creating index
Seeking key: -4
Seeking key: 45000
Seeking key: 2501
Seeking key: 56000
Real: 00:00:00.734, CPU: 00:00:00.727 ...

Again the index is created just before the seek of the first key and the index isn’t created again.

Summary

What we’ve done is take a curried function and turn it into a higher order function. By making this change we’ve improved the performance of our function when doing multiple lookups. We used the lazy computation to remove the initial index creation if we don’t do any lookups. This was a fun experiment.

Full Source Code

Improving an Old Pattern Continued

The active patterns we’ve seen so far are enough to take some complex code and make it clean and readable. Let’s take the active patterns we know and improve the pattern matching code we created earlier.

Reviewing the Code

We were reviewing a chunk of code to determine whether a client requires an update based on the version numbers. Here is where we left off with the pattern match.

let checkForUpdate (rMaj, rMin, rBld) userVer = 
    match userVer with
    | (uMaj, _, _) 
        when rMaj > uMaj                                     
            -> Major
    | (uMaj, uMin, _) 
        when rMaj = uMaj && rMin > uMin                   
            -> Minor
    | (uMaj, uMin, uBld) 
        when rMaj = uMaj && rMin = uMin && rMin > uBld 
            -> Build
    | _     -> NoUpdate

The match is checking the major version, followed by the minor, and the build. The issue I have with this pattern match is we keep having to compare values we already know. As the match falls through the patterns we end up checking the major version three times. This isn’t very readable.

Adding a Partial Active Pattern

The first thing we can do is add a partial active pattern to match on all the cases that don’t require an update. We can leverage the fact that F# does structural equality by default that we can do this quite easily.

let (|NoUpdatePartial|_|) (relVer, userVer) =
    if relVer <= userVer then Some ()
    else None

With this partial pattern we've now eliminated the need to do multiple comparisons of any individual values.

Combining Active Patterns

We'll take the partial active pattern and use it in a multicase active pattern. Our multicase pattern needs only be concerned with matching the individual version values. This is providing we add the partial active pattern before the individual value patterns. It will look something like this:

let (|Major|Minor|Build|NoUpdate|) (relVer, userVer) =
    match (relVer, userVer) with
    | NoUpdatePartial                        -> NoUpdate
    | (rMaj,_,_),(uMaj,_,_) when rMaj > uMaj -> Major
    | (_,rMin,_),(_,uMin,_) when rMin > uMin -> Minor
    | _                                      -> Build

We now have a complete active pattern we can use when determining what kind of update is required.

let checkForUpdate relVer userVer =
    match relVer, userVer with
    | Major    -> doMajorUpdate ()
    | Minor    -> doMinorUpdate () 
    | Build    -> doBuildUpdate ()
    | NoUpdate -> doNoUpdate ()

Summary

We’ve greatly increased the expressiveness of our pattern matching by using Active Patterns. We’ve used a Partial Active Pattern and a Multi-Case Active Pattern. Active pattern can be combined together to create larger patterns all in the name of readability. All of this helps lead us to correct and expressive solutions.

Partial Active Patterns

There are four kinds of active patterns. We’ve already looked at the Single and Multicase Active Patterns. We’ll now look at Partial Active Pattern.

Partial Active Pattern

A partial active pattern is used when the match expression needs to be transformed in different ways for the individual patterns. Partial active patterns are mutually exclusive in that they don’t necessarily have to relate to the other patterns.

We define the partial active pattern using the banana clips, a label, and an underscore. We identify a successful match by returning Some value and a non match with None.

let (|StartsWithCapital|_|) (v : string) = 
    if v.[0] |> System.Char.IsUpper then Some v
    else None

We can use the active pattern in our match expressions for readability.

let processFile (filePath : string) =
    filePath |> System.IO.File.ReadAllLines
      |> Seq.filter (function StartsWithCapital _ -> true
                            | _                   -> false)

Our processFile function takes in a file, reads all the lines, and then gives us a sequence of lines that begin with a capital letter. There is an issue though. We are using an indexer (v.[0]) on the string in our active pattern which will fail if the value is null or empty. Let’s add another partial active pattern.

let (|NullOrEmptyLine|_|) (v : string) = 
    if System.String.IsNullOrEmpty v then Some ()
    else None

The filter of the processFile will now look like:

Seq.filter (function NullOrEmptyLine     -> false
                   | StartsWithCapital _ -> true
                   | _                   -> false)

The order in which we place the pattern expressions matters. We have to do the EmptyLine pattern match before the StartsWithCapital or we will end up with the same error as before.

Putting it to use

We’ve received some specifications for interfacing with an old system. The system streams a sentence per line. A sentence is identified by the starting capital letter of the sentence. There are some issues with the system. Every once in a while the system will send a sentence in reverse or it will send garbage data (no starting or ending capital letter). Some lines may be null and they should be converted to newlines. Format the incoming data where all sentences are not reversed and include the empty lines.

Based on the specs above we have four cases:

  • Normal sentence
  • Reversed sentence
  • Empty line
  • Garbage data

We seem to already have 2 partial patterns for this exercise which means we only need one more to fulfill our requirements. The reversed sentence.

let (|EndsWithCapital|_|) (v : string) =
    if v.[v.Length - 1] |> System.Char.IsUpper then Some v
    else None

With the final partial active pattern in place we can setup our pattern match to fix the streamed data.

let reverseString : string -> string = 
    Seq.rev >> Seq.toArray >> (fun s' -> new string(s'))

let mungeLine = function
    | NullOrEmptyLine     -> Some "\n"
    | StartsWithCapital s -> Some s
    | EndsWithCapital s   -> s |> reverseString |> Some
    | _                   -> None

Taking my word that the funny syntax in the reverseString function actually reverses a string, we can see the mungeLine function uses our partial active patterns for validating the data. Partial active patterns have made out match expressive and readable to non coders.

Summary

Partial active patterns give us a means to do pattern matching when it may seem like the patterns have nothing in common. Partial active patterns allow us to transform the value we are matching before evaluating the pattern. We have not added partial active patterns to our collection of tools to create readable and expressive code.

Introducing Active Patterns

We’ve been working with pattern matching in F# for awhile and we are ready to dive into Active Patterns. There are 16 different patterns we can match on right out of the box. For the cases where the base patterns aren’t enough we can use Active Patterns to pick up the slack. There are four kinds of active patterns. We’ll begin by looking at two kinds of active patterns.

Single-Case Active Patterns

This kind of active pattern isn’t used all that often. A Single-Case Active Pattern can be thought of as a view or a subset of data from an object. This gives us the option of matching on some of the data or transforming the data into something useful.

#r "System.Windows.Forms"
open System.Windows.Forms

let (|Position|) (ctrl : Control) = ctrl.Left, ctrl.Top

let (|Size|) (ctrl : Control) = ctrl.Width, ctrl.Height

let (|PositionAndSize|) (ctrl : Control) = 
    match ctrl, ctrl with
    | Position p, Size s -> p, s

The System.Windows.Forms.Control class has over 30 properties. We can group related properties together using single-case active patterns. We’ve defined some patterns which can be used to match on properties we may be interested. We’ve created active patterns for Position, Size, and a combination of the two.

We can use our active patterns in other functions to make our code more expressive.

let printPosition ctrl =
    match ctrl with
    | Position (x,y) -> printfn "Left = %d, Top = %d" x y

We can use a pattern matching shorthand to make the function more concise.

let printPosition = function 
    | Position (x,y) -> printfn "Left = %d, Top = %d" x y

Multicase Active Patterns

The Multicase Active Pattern is more commonly used than the single-case active pattern. We partition the input domain into a known set of possible values. The multicast active pattern is a closed set of values and therefore a successful match must be returned. As of F# version 4.1 there is an upper limit of 7 values you can define in a multicase active pattern.

Let’s categorize scores in the game of darts. We can place a score into a finite set of possibilities. An invalid score is anything less than 0 or more than 180. We’ll mark scores of 150 and 180 as being special. Anything between 150 and 180 will be a high ton. A score between 100 and 150 will be classified a low ton. The rest will be standard points.

We’ll create a multicase active pattern to improve the readability of our pattern match.

let (|LowTon|Ton50|HighTon|Ton80|Points|Invalid|) x =
    if x < 0 || 180 < x then Invalid
    elif x = 150 then Ton50
    elif x = 180 then Ton80
    elif x < 100 then Points x
    elif x < 150 then LowTon x
    else HighTon x

This example isn't terribly unreadable. Creating the active pattern does allow us to define the potentially misunderstood code once and then use the clear and concise patterns throughout the rest of the application.

let printScore = function
  | Points pts  -> printfn "%d points." pts
  | LowTon pts  -> printfn "Low ton of %d points." pts
  | Ton50       -> printfn "One hundred and fifty!"
  | HighTon pts -> printfn "Wahoo! High ton of %d points!" pts
  | Ton80       -> printfn "Onnneeee Hundred and eightyyyyyy!!!!"
  | Invalid     -> printfn "Score must be between 0 and 180."

Summary

A single-case active pattern is good for creating a view of a complex or large model. We can define subsets of properties or values we require from the model which can be pattern matched. The single-case active pattern has a limited use case and isn't used very often. Multicase active patterns are good when your input can be categorized into a finite set of values. Multicase active patterns are used quite regularly in combination with other kinds of active patterns.

Improving an Old Pattern

I wrote a blog post called Some(“F#”) is better than None back in 2015. I’ve grown quite a bit as a developer since then. Growth is what we strive for in this industry. Looking back over the blog post, I would like to improve upon the code to make it more expressive and bug free. The code I am focused on is comparing assembly versions to indicate whether an update would be required. The original code looked similar to this:

let checkForUpdate (rMaj, rMin, rBld) userVer =
    match (uMaj, uMin, uBld) with
    | (x, _, _)       when x < rMaj -> "Major"
    | (rMaj, x, _)    when x < rMin -> "Minor"
    | (rMaj, rMin, x) when x < rBld -> "Build"
    | _                             -> "None” 

My first instinct of change would be to return a Discriminated Union instead of a string. Using a discriminated union would give me type safety as well as better pattern matching later on in in other functions. I would define the discriminated union as:

type UpdateType =
    | Major
    | Minor
    | Build
    | NoUpdate

The checkForUpdate function would then look like:

let checkForUpdate (rMaj, rMin, rBld) userVer =
    match (uMaj, uMin, uBld) with
    | (x, _, _)       when x < rMaj -> Major
    | (rMaj, x, _)    when x < rMin -> Minor
    | (rMaj, rMin, x) when x < rBld -> Build
    | _                             -> NoUpdate 

This is a minor change with big benefits. Other functions handling the result can now pattern match on the type safe discriminated union instead of the infinite variations of potential string values.

Expanding the guards

I decided to add some tests for the function. I used FsCheck (a property based testing library) to battle test the function. This turned out to be a useful exercise as an issue was identified. The patterns were not handling the case correctly for a user who has an alpha or beta version which is considered a higher version than the current release.

To resolve the issue I ended up having to expand the guard clauses. I made the mistake of shadowing the release version labels rMaj and rMin. I had thought they would match the value contained in the labels, similar to an erlang pattern match. I was wrong. Shadowing a label means the system creates a new label of the same name within the current/nested scope.

let checkForUpdate (rMaj, rMin, rBld) userVer = 
    match userVer with
    | (uMaj, _, _) 
        when rMaj > uMaj                                     
            -> Major
    | (uMaj, uMin, _) 
        when rMaj = uMaj && rMin > uMin                   
            -> Minor
    | (uMaj, uMin, uBld) 
        when rMaj = uMaj && rMin = uMin && rMin > uBld 
            -> Build
    | _     -> NoUpdate

After the guard expansions all my tests passed. Although it works, this pattern match isn’t as expressive as we may like. Going forward, we should look into using Active Patterns.

Summary

There are some things to be aware of when using pattern matching. We can’t compare bound values directly in the pattern, we have to use a guard clause to compare them. Attempting to match bound values in the pattern will not match and will create a shadowed value. Use discriminated unions (DU) when given the choice for patterns. DUs improve the type safety of our functions and limit the number of variations our functions have to account for. Passing strings into functions have an infinite number of variations and for the most part be avoided. Sometimes making some small changes can make for more robust functions.

Asynchronous Child

Looking back at Running with Async we saw that you can run asynchronous workflows in multiple ways. We can use Async.RunSynchronously when we require the return value. We also looked at Async.Start when we don’t need a result. We also saw an example of running multiple asynchronous workflows using Async.Parallel. Let’s take a moment and get introduced to another means of starting asynchronous workflows.

Starting Children

We can use Async.StartChild when we want to evaluate an asynchronous workflow and get the result at a later time. This can be useful when aggregating data from multiple sources. Imagine having to hit multiple web servers or database servers to pull in data for analysis. We can start the workflows as children and get their results individually.

let getUrlContentSizeAsync (url : string) = 
    async {
        let request   = WebRequest.Create (url)
        use! response = request.AsyncGetResponse ()
        use stream    = response.GetResponseStream ()
        use reader    = new StreamReader(stream)
        let content   = reader.ReadToEnd() 
        do! Async.Sleep 500
        return (url,content.Length)
    }

let run1 = async {
        let! child = getUrlContentSizeAsync "http://techandwings.ca" 
                     |> Async.StartChild
        return! child
    }

run1 |> Async.RunSynchronously

In the function run1 we are using Async.StartChild to start the retrieving the content size for the URL. We are immediately returning the result from the child by using return!. Let’s add another URL.

let run2 = async {
        let! child1 = getUrlContentSizeAsync "http://techandwings.ca" 
                      |> Async.StartChild
        let! result1 = child1

        let! child2 = getUrlContentSizeAsync "http://nhl.com" 
                      |> Async.StartChild        
        let! result2 = child2

        return (result1, result2)
    }

run2 |> Async.RunSynchronously

When we start the run2 workflow we now receive a tuple containing the results of the two URLs we are retrieving. We start child1, wait for child1 to finish, start the child, and wait for its results. We’ve created our asynchronous workflow to retrieve the URL sizes sequentially. This is not an ideal use of the workflows. Let’s see if we can improve this by making a minor change.

let run3 = async {
        let! child1 = getUrlContentSizeAsync "http://techandwings.ca" 
                      |> Async.StartChild

        let! child2 = getUrlContentSizeAsync "http://nhl.com" 
                      |> Async.StartChild

        let! result1 = child1        
        let! result2 = child2

        return (result1, result2)
    }

run3 |> Async.RunSynchronously

Looking at run3 we can see we are starting the asynchronous workflows for both URLs before waiting for either result. The retrieval of the URLs’ sizes will happen concurrently. We then wait for the results of the child workflows and return them. This is a more effective use of Async.StartChild as we are now doing execution concurrently which can produce performance benefits when waiting for multiple long running IO operations.

If we enable #time in the REPL we should see a noticeable difference between run2 and run3. The difference is compounded by the Async.Sleep inserted in the getUrlContentSizeAsync function. You should see at least a half second speed up from run3 compared to run2.

Summary

Async.StartChild gives us the ability to control when start the asynchronous workflow and when we want the result. This in turn allows us to execute controlled asynchronous workflows concurrently. Executing asynchronous workflows as children is ideal for aggregating data from multiple sources.

Running with Async

Creating an asynchronous workflow doesn’t execute it immediately. It’s up to us to determine when and how we want the workflow to execute. So far we’ve been using Async.RunSynchronously to run our asynchronous workflow. By doing so, we are saying execute the async and wait for the result. This may not always be what we need. What if we want to write to a log file without blocking the current execution? We could use Async.Start.

Let’s revisit some code we looked at earlier. (Asyncing the F# Way)

let waiting () =
    async {
        printfn "Good night"
        do! Async.Sleep 2000
        printfn "Good morning"
    } |> Async.RunSynchronously
    printfn "Hello"

We get the expected results of:

Good night
Good morning
Hello

If we make a small change…

let nowaiting () =
    async {
        printfn "Good night"
        do! Async.Sleep 2000
        printfn "Good morning"
    } |> Async.Start
    printfn "Hello"

We’ve change the Async.RunSynchronously to Async.Start and our results are much different. We end up with results like this:

Hello
Good night
Good morning

(You’re results may be slightly different, however the “Hello” should always come before “Good morning”)

The reason Hello should always come before Good morning is we are no longer waiting for the result of the asynchronous expression. We are starting the asynchronous code and continuing on with the next expression.

Async.Parallel

We can use Async.Parallel when we have multiple asynchronous objects. This in turn can give some performance gains as multiple tasks are executed concurrently. We’ll use the getUrlContentsizeAsync and query some websites and sort them by size in descending order.

open System.IO
open System.Net

let getUrlContentSizeAsync (url : string) = 
    async {
        let request   = WebRequest.Create (url)
        use! response = request.AsyncGetResponse ()
        use stream    = response.GetResponseStream ()
        use reader    = new StreamReader(stream)
        let contents  = reader.ReadToEnd ()
        return (url,contents.Length)
    }

let sites = ["http://techandwings.ca"; 
             "http://www.cnn.com"; 
             "http://www.foxnews.com";
             "http://msnbc.com";
             "http://google.ca";
             "http://nhl.com";
             "http://mlb.com";
             "http://nfl.com"]

let asyncSites = sites |> List.map getUrlContentSizeAsync

In the REPL you can turn on some statistics analysis by entering the command:

#time;;

Let’s start by executing the list of asyncSites sequentially.

asyncSites |> List.map Async.RunSynchronously |> Seq.sortByDescending snd

The average results of running them sequentially a few times turned out to be around 4 seconds. (Your results may vary)

Real: 00:00:03.720, CPU: 00:00:00.869, GC gen0: 1, gen1: 0
val it : seq =
  seq
    [("http://nhl.com", 537569); ("http://mlb.com", 491099);
     ("http://nfl.com", 196920); ("http://www.cnn.com", 135159); ...]

If we make a couple of changes to the execution we should be able to speed it up. Let’s add Async.Parallel in exchange for the list map.

asyncSites |> Async.Parallel |> Async.RunSynchronously |> Seq.sortByDescending snd

The results of our new execution:

Real: 00:00:01.845, CPU: 00:00:00.820, GC gen0: 1, gen1: 0
val it : seq =
  seq
    [("http://nhl.com", 536551); ("http://mlb.com", 491099);
     ("http://nfl.com", 196920); ("http://www.cnn.com", 135159); ...]

My average results for running with Async.Parallel was just under 2 seconds. We’ve improved the performance of our experiment with a very minor change in how we are executing the asynchronous objects.

Summary

We’ve seen some new ways to run our asynchronous workflows. We have Async.RunSynchronous when we want to wait for the result. We can also start an asynchronous workflow without waiting for anything by using Async.Start. We’ve looked at the ability to chain multiple workflows into a list and execute them either sequentially or in parallel with the help of Async.Parallel. Running multiple asynchronous workflows in parallel can have some very drastic performance improvements. It’s always recommended to test and analyze any kind of enhancements to be sure. A very simple starting point for analysis is using the #time directive. Enabling #time will display some basic statistics about the code we are executing in the REPL.

Asyncing the F# Way

I recently gave a talk at the Winnipeg .Net User Group. This talk was focused on features of F# that are going to make their way into the world of C#. During the presentation I was talking about using local functions to wrap async functions. It was at this point someone asked if F# can do async/await. Well, the answer is yes.

The Async Builder

F# uses an Async Computation Expression for creating asynchronous workflows. The notation we use to denote an async computation is the async { ... }. Anything inside the curly braces are executed within the computation expression.

async {
    printfn "Good night"
    do! Async.Sleep 2000
    printfn "Good morning"
} |> Async.RunSynchronously

Looking at the example above, we have our async { ... } and our code within the curly braces. If you run the code in your REPL (Read Evaluate Print Loop) it will print “Good night”, wait 2 seconds, then print “Good morning”.

The Bang notation

The do! (do-bang) is our way of expressing we are evaluating an asynchronous expression. The do itself indicates we don’t care about the result. It’s the ! (bang) that the AsyncBuilder uses to unwrap the asynchronous expression’s result. It’s syntactic sugar to ensure our code is expressive and readable.

We use let! (let-bang) when we want to use the result of an asynchronous expression. In the doWorkAsync example below, we use the let! to bind the result of addAsync to the label result so we can print it.

let addAsync x y = async { return x + y }

let doWorkAsync = async {
    let! result = addAsync 4 6
    printfn "Result: %d" result
    }

Async.RunSynchronously doWorkAsync

Binding IDisposable

When we have an asynchronous expression which returns an object implementing IDisposable we should bind the result with use!. This unwraps the asynchronous expression, binds the disposable object, and disposes of the object when it falls out of scope. An example of use! is when retrieving the contents asynchronously from a website.

open System.IO
open System.Net

let getUrlContentSizeAsync (url : string) = 
    async {
        let request   = WebRequest.Create (url)
        use! response = request.AsyncGetResponse ()
        use stream    = response.GetResponseStream ()
        use reader    = new StreamReader(stream)
        let contents  = reader.ReadToEnd ()
        return (url,contents.Length)
    }

getUrl "http://techandwings.ca" |> Async.RunSynchronously

In the code above we are using the use! to unwrap the IDisposable response object. This in turn performs an automatic clean up when the object is no longer required.

Summary

We write asynchronous code in F# using the AsyncBuilder. The builder itself is syntactic sugar allowing us to write clean and expressive code. We use the Bang notation to unwrap the asynchronous calls within the builder. There are do!, let!, and use! to handle the results of an asynchronous expression. We’ve currently only looked at running the asynchronous code one way using the Async.RunSynchronously. We’ll look at more ways of running our code in a future post.

Winnipeg Azure Bootcamp 2017

The Global Azure Bootcamp 2017 hosted by the Winnipeg .Net User Group was a success. There was a good number of people in attendance for the event. The presentations were excellent which made it difficult to choose some standout topics. In saying that, here are a few items that I brought back from the event to dig in deeper.

Azure Functions with F#

The ability to create Azure functions which run F# has to be the big takeaway for me. An Azure function is Microsoft’s vision of a serverless architecture. The idea is we don’t need to worry about scaling web applications as that is handled automatically by Azure. Azure functions run based on a script file we code. F# has a very good story for prototyping using the REPL and F# script files (fsx). See what I’m thinking? This is a great opportunity to go from prototype to testing in the cloud with possibly little friction.

Let’s give it a quick go.

Open up your Azure portal and add a new “Function App”. Enter in the required details, App name, Subscription, Resource Group, … etc. Once everything is created you can click on your new function. Click the plus sign to the right of “Functions”, then scroll down and click “Custom function”. You can filter the “Language” to F# using the drop down. Select HttpTrigger-FSharp as the template for our function. Name your function and click create.

The new function comes with some template code in the online editor. We can replace the default code in the file “Run.fsx” with:

#r "System.Net.Http"

open System.Net
open System.Net.Http

let Run(req: HttpRequestMessage, log: TraceWriter) =
    req.CreateResponse(HttpStatusCode.OK, "F# and Azure Functions FTW!")

Click the “Save” and “Run” button and we should see our message in the result pane in the bottom right.

Azure functions and F# are going to be an unstoppable combination.

Docker Everywhere

We saw a great demo on the ability to upload and create docker containers in Azure. The presenter, Alexander Trauzzi, created a TypeScript application with Geotagging and deployed it in a docker image. He then loaded the same docker image to multiple Azure data centers around the world. After a bit of answering questions, the map of the world started to display little Azure clouds. It was very cool.

Alex setup a guide you can follow if you want to try the demo yourself.
https://github.com/atrauzzi/azure-bootcamp-2017/blob/master/guide_local.md

Testing in Production

Testing in production allows you to have multiple deployment slots for an Azure website and set differing amounts of traffic to each. There is no misconception with the name of this feature. You are literally testing in production, however this is more of a controlled production test.

In order to try this out, create your App Service in a standard or premium plan.

Here are some rough steps to get setup:

  1. In the Deployment group of your app service, click on Deployment Slots.
  2. Click on Add Slot to create a new deployment slot.
  3. In the Development Tools group, click on Testing in production.

You should now be able to click the drop down which says Choose deployment slot, and change the traffic percentage we want to route to that deployment.

This gives us a way to control the amount of testing traffic to the new version of our site. Once we are satisfied of the new site’s stability, we can use switch the sites using the Swap button from the app’s Overview.

Summary

My big three takeaways from Global Azure Bootcamp 2017 was F# with Azure Functions, deploying and running our Docker images in Azure, and testing in production.

Deconstructing Records

Deconstruction let us focus on the values we want to match in our patterns. We’ve shown we can deconstruct tuples, but what about records? Absolutely.

A record is a data structure with named values. Records are immutable by default. We use records in exchange of tuples. Records give better context to what data is being represented. We’ll use the Astronaut record defined below as our data representation.

type Astronaut = { Name : string; Year : int }

Suppose we want to print an appropriate message based on the astronaut’s name. We’ll do a simple greeting for all astronauts except for “Dave” and “Neil”. We can create our function with a pattern match as below.

let greeting astronaut = 
    match astronaut with
    | {Name = "Dave"} -> "I'm sorry Dave, I'm afraid I can't do that."
    | {Name = "Neil"} -> "The first person to set foot on the moon."
    | {Name = name}   -> sprintf "Hello %s." name

If you look at the patterns in the match you will note we are deconstructing the Name value from the astronaut argument. Someone reading the code can easily see we are interested in the astronaut’s name.

We could be even more specific with matching on our Astronauts by using patterns below:

let greeting astronaut = 
    match astronaut with 
    | {Name = "Dave"; Year = 2001 } 
         -> "I'm sorry Dave, I'm afraid I can't do that."
    | {Name = "Neil"}               
         -> "The first person to set foot on the moon."
    | {Name = name}                 
         -> sprintf "Hello %s." name

We’ve gone further in isolating the values we want for our patterns. The more values you add the more specific your patterns become. In the example above we have a case using the Name and Year deconstructed from the astronaut to get Hal’s response to Dave. All other astronauts named Dave will get the standard greeting.

Deconstruct OR what…

Let’s go back to matching on name only. What if our name isn’t proper case? What if Dave is actually a “dave” or “DAVE”? We may still want to match on those “Dave”s. Here is where some of the power of F#’s pattern matching starts to shine. We can write our pattern to include those other “Dave”s by combining deconstruction and the OR Pattern.

let greeting astronaut = 
    match astronaut with
    | {Name = "Dave" | "dave" | "DAVE"} 
        -> "I'm sorry Dave, I'm afraid I can't do that."
    | {Name = "Neil"} 
        -> "The first person to set foot on the moon."
    | {Name = name}   
        -> sprintf "Hello %s." name

We’ve certainly improved our pattern to include more cases of “Dave”. We can take our pattern one step further and make our patterns case insensitive. The first way will be more familiar for OOP developers. We can use the property accessor to get the Name to then lower and use the property again to print the name. The other way would be to use a pattern match in the function signature. We can do pattern matching and deconstructing in the function arguments.

let greeting astronaut = 
    match astronaut.Name.ToLower() with
    | "dave" 
        -> "I'm sorry Dave, I'm afraid I can't do that." 
    | "neil" 
        -> "The first person to set foot on the moon."
    | _      
        -> sprintf "Hello %s." astronaut.Name


let greeting' {Name=name} = 
    match name.ToLower() with
    | "dave" 
        -> "I'm sorry Dave, I'm afraid I can't do that."
    | "neil" 
        -> "The first person to set foot on the moon."
    | _      
        -> sprintf "Hello %s." name

It’s not overly common to use deconstruction in the function signature. It can lead to some ambiguity in the code. We are focusing on the values we care about, however the function signature may no longer have the same readability it did before with the astronaut value.

Summary

We’ve covered the ability to deconstruct records in our patterns. We aren’t limited to one value for deconstruction. We can match on any number of values in a record, and the number of values can vary between patterns. F# is not limited to only deconstruct records in the match with construct. Matching can be used by the function construct and in the declaration of function arguments. We can also combine deconstruction with OR to reduce the number of patterns and improve readability. It’s the ability to combine patterns which let’s the power of F# shine its expressiveness.