F#: Computation Expressions (sad path)

The following example demonstrates how I can empower my client to decide how to handle sad-path scenarios versus the server.

In this example, I rely on Partial Application to inject my handler for a user not being authenticated.

The following code reflects my client passing in a sad-path handler:

(*Client*)
let onFailure  credentials = printf "Authentication failed: %A" credentials

let result = { UserName= UserName "Bizmonger"
               Password= Password "MyPasswordxxx" } 
             |> authenticate onFailure

The authenticate function requires a sad-path handler as an argument and will invoke that handler using Partial Application.

In this example, I pass in the credentials of the attempted login for the handler to operate on:

let authenticate onFailure credentials = 
    getAuthentication { 
        let!   result = if credentials.UserName = UserName "Bizmonger"  &&
                           credentials.Password = Password "MyPassword"
                
                        then Some { FirstName=FirstName "Scott"
                                    LastName= LastName  "Nimrod"
                                    Balance=  Balance    99.99m }
                        else onFailure credentials
                             None 
        return result }
 

Here’s the entire example below:

(*Types*)
type UserName =  UserName  of string
type Password =  Password  of string
type FirstName = FirstName of string
type LastName =  LastName  of string
type Balance =   Balance   of decimal
 
type Credentials = { UserName:UserName;   Password:Password }
type Account =     { FirstName:FirstName; LastName:LastName; Balance:Balance }
 
type GetAuthenticationBuilder() =
    member this.Bind (account, f) = printf "Logged In: %A\n\n" account; f account
    member this.Return x   = x
 
(*Functions*)
let getAuthentication = GetAuthenticationBuilder()

let authenticate onFailure credentials = 
    getAuthentication { 
        let!   result = if credentials.UserName = UserName "Bizmonger"  &&
                           credentials.Password = Password "MyPassword"
               
                        then Some { FirstName=FirstName "Scott"
                                    LastName= LastName  "Nimrod"
                                    Balance=  Balance    99.99m }
                        else onFailure credentials
                             None 
        return result }

(*Client*)
let onFailure  credentials = printf "Authentication failed: %A" credentials

let result = { UserName= UserName "Bizmonger"
               Password= Password "MyPasswordxxx" } 
             |> authenticate onFailure
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: