Dogs Chasing Squirrels

A software development blog

Tag Archives: F#

Railway-Oriented Programming in F# and WebAPI

0

If you’re interested in learning about using railway-oriented programming in F#, you should be reading Railway oriented programming at fsharpforfunandprofit.com and The Marvels of Monads at microsoft.com. Stylish F# by Kit Eason has also been a help.

Functional programming is about functional composition and pipelineing functions from one to the next to get a result. Railway-oriented programming is about changing that pipeline to a track where if an operation succeeds, it goes forwards and if it fails, it cuts over to a failure track. F# already has built-in the Result object, a discriminated union giving success (Ok) or failure (Error) and the monadic functions, bind, map, and mapError.

I was interested in how these could be applied to a WebAPI endpoint. Let’s say we’re passing these results along a pipeline. What’s failure? In the end, it will be an IActionResult of some kind, probably a StatusCodeResult. 404, 401, 500, whatever. In the end, that’s an IActionResult, too, though with a status code of 200.

There’s an F#, functional web project that already does something like this, Suave.io, though it doesn’t look to be maintained anymore. Even so, they have some good, async implementations of the various railway/monadic functions like bind, compose, etc. I’ve tried to adapt them in to my own AsyncResult module.

Result

The result object is unchanged:

type Result<'TSuccess,'TFailure> =
    | Ok of 'TSuccess
    | Error of 'TFailure

Bind

First, bind, which takes some Result input and a function and, if the input is Ok, calls the function with the contents, and, if the input is Error, short-cuts and returns the error.
An async bind looks like this:

let bind f x = async {
    let! x' = x
    match x' with
    | Error e -> return Error e
    | Ok x'' -> return! f x''
}

Map

Next we have map. Say we have a function that takes some object and manipulates it returning another object. Map lets us insert that into our railway, with the function operating on the contents of the Ok result.
An async map looks like this:

let map f x = async {
    let! x' = x
    match x' with
    | Error e -> return Error e
    | Ok x'' ->
        let! r = f x''
        return Ok( r )

MapError

MapError is like map but instead we expect the function to operate on the Error result.
This is my async mapError:

let mapError f x = async {
    let! x' = x
    match x' with
    | Error e ->
        let! r = f e
        return Error( r )
    | Ok ok ->
        return Ok ok
}

Compose

Next we have compose, which lets us pipe two bound functions together. If the first function returns an Ok(x) as output, the second function takes the x as input and returns some Result. If the first function returns an Error, the second is never called.
This is the async compose:

let compose f1 f2 =
    fun x -> bind f2 (f1 x)

Custom Operators

We can create a few custom operators for our functions:

// bind operator
let (>>=) a b =
    bind b a

// compose operator
let (>=>) a b =
    compose a b

An Example WebAPI Controller

Let’s imagine a WebAPI controller endpoint that implements GET /thing/{id} where we return some Thing with the given ID. Normally we would:
* Check that the user has permission to get the thing.
* Get the thing from the database.
* Format it into JSON.
* Return it.
If the user doesn’t have permissions, we should get a 401 Unauthorized. If the Thing with the given ID isn’t found, we should get a 404 Not Found.

The functions making up our railway

Usually we want a connection to the database but I’m just going to fake it for this example:

let openConnection(): Async<IDbConnection> =
    async {
        return null
    }

We might also have a function that, given the identity in the HttpContext and a database connection could fetch the user’s roles. Again we’ll fake it. For testing purposes, we’ll say the user is an admin unless the thing ID ends in 99

let getRole ( connection : IDbConnection ) ( context : HttpContext ) =
    async {
        if context.Request.Path.Value.EndsWith("99") then return Ok "user"
        else return Ok "admin"
    }

Now we come to our first railway component. We want to check the user has the given role. If he does, we return Ok, if not an Error with the 401 Unauthorized code (not yet a StatusCodeResult)

let ensureUserHasRole requiredRole userRole =
    async {
        if userRole = requiredRole then return Ok()
        else return Error( HttpStatusCode.Unauthorized )
    }

Next we have a railway component that fetches the thing by ID. For testing purposes, we’ll say that if the ID is 0 we’ll return an Option.None and otherwise return an Option.Some. Although I haven’t added it here, I could imagine adding a try/catch that returns an Error 500 Internal Server Error when an exception is caught.

let fetchThingById (connection: IDbConnection) (thingId: int) () =
    async {
        match thingId with
        | 0 ->
            // Pretend we couldn't find it.
            return Ok( None )
        | _ ->
            // Pretend we got this from the DB
            return Ok( Some ( { Id = thingId; Name = "test" } ) )
    }

Our next railway component checks that a given object is found. If it’s Some, it returns Ok with the result. If it’s None, we get an Error, 404 Not Found.

let ensureFound ( value : 'a option ) = async {
    match value with
    | Some value' -> return Ok( value' )
    | None -> return Error( HttpStatusCode.NotFound )
}

Next we’ll create a function that just converts a value to a JSON result (maybe pretending there might be more complicated formatting going on here):

let toJsonResult ( value : 'a ) =
    async {
        return ( JsonResult( value ):> IActionResult )
    }    

Finally, we’ll add a function to convert that HttpStatusCode to a StatusCodeResult (also overkill – we could probably inline it):

let statusCodeToErrorResult ( code : HttpStatusCode ) = async {
    return ( StatusCodeResult( (int)code ) :> IActionResult )
}

When we end up, we’re going to have an Ok result of type IActionResult and an Error, also of type IActionResult. I want to coalesce the two into whatever the result is, regardless of whether it’s Ok or Error:

// If Error and OK are of the same type, returns the enclosed value.
let coalesce r = async {
    let! r' = r
    match r' with
    | Error e -> return e
    | Ok ok -> return ok
}

Putting it together

Here’s our railway in action:

// GET /thing/{thingId}
let getThing (thingId: int) (context: HttpContext): Async<IActionResult> =
    async {
        // Create a DB connection
        let! connection = openConnection()
        // Get the result
        let! result =
            // Starting with the context...
            context |> (
                // Get the user's role
                ( getRole connection )
                // Ensure the user is an admin.  
                >=> ( ensureUserHasRole "admin" )
                // Fetch the thing by ID
                >=> ( fetchThingById connection thingId ) 
                // Ensure if was found
                >=> ensureFound
                // Convert it to JSON
                >> ( map toJsonResult )
                // Map the error HttpStatusCode to an error StatusCodeResult
                >> ( mapError statusCodeToErrorResult )
                // Coalese the OK and Error into one IAction result
                >> coalesce
            )
        // Return the result
        return result
}

To summarize, we
* Get the user’s role, resulting in an Ok with the role (and no Error, though I could imagine catching an exception and returning a 500).
* See if the user has the role we need resulting in an Ok with no content or an Error(401).
* Fetch a Thing from the database, resulting in an Object.Some or Object.None.
* Check that it’s not None, returning an Error(404) if it is or an Ok(Thing).
* Mapping the Ok(Thing) into a Thing and turning the Thing into a JsonResult.
* or mapping the Error(HttpStatusCode) into a HttpStatusCode and turning the Error(HttpStatusCode) into a StatusCodeResult.
* Taking whichever result we ended up with, the JsonResult or StatusCodeResult and returning it.

If we run the website and call https://localhost:5001/thing/1 we get the JSON for our Thing.

{"id":1,"name":"test"}

If we call /thing/0 we get 404 Not Found. If we call thing/99 we get 401 Unauthorized.

There’s room here for some other methods. I could imagine wanting to wrap a call in a try/catch and return a 500 Server Error if it fails, for example.

The best part is that it’s a nice, readable, railway of functions. And our custom operators make it look good.

The code for this post can be found on GitHub.

F# and Swift

0

I’m looking at Apple’s Swift language and it’s interesting to see how similar it is to F# (which itself is similar to Scala and Haskell). I think this is all in reaction to the trouble we’re having in general with pure object-oriented programming and the advantages of a functional (or at least hybrid) approach in the age of distributed systems.

Value declaration

This is some F# for assigning variables:

let someConstant = 10
let mutable someVariable = 1.23
let specifyTypeExplicitly : String = "blah"

and in Swift:

let someConstant = 10 
var someVariable = 1.23
var specifyTypeExplicitly : Double = "blah"

let mutable for var, otherwise the same. Types are generally inferred but can be set explicitly.

Both languages have tuples and dictionaries assigned in basically the same way.

Pattern matching

Instead of F#’s match, Swift puts its matching inside a traditional switch statement.

//let rgba = ( 1.0, 1.0, 1.0, 1.0 ) "white"
//let rgba = ( 0.4, 0.4, 0.4, 1.0 ) "gray"
//let rgba = ( 0.0, 0.6, 0.8, 1.0 ) "blue is 0.8"
let rgba = ( 0.0, 0.6, 0.8, 1.0 )
switch rgba {
case ( 1.0, 1.0, 1.0, 1.0 ):
    print( "white" )
case let ( r, g, b, 1.0) where r==g && g==b:
    print("gray")
case (0.0, 0.5...1.0, let b, _):
    print("blue is \(b)")
default:
    break
}

In F#, this would be something like (this is from memory):

//let rgba = ( 1.0, 1.0, 1.0, 1.0 ) "white"
//let rgba = ( 0.4, 0.4, 0.4, 1.0 ) "gray"
//let rgba = ( 0.0, 0.6, 0.8, 1.0 ) "blue is 0.800000"
let rgba = ( 0.0, 0.6, 0.8, 1.0 )
match rgba with
| ( 1.0, 1.0, 1.0, 1.0 ) ->
    printfn "white"
| ( r, g, b, 1.0 ) when ( r = g ) && ( g = b ) ->
    printfn "gray"
| ( 0.0, g, b, _ ) when ( g >= 0.5 ) && ( g <= 1.0 ) ->
    printfn "blue is %f" b 
| _ -> ()

Some and None

Swift and F# both support the Some and None keywords for optional values. e.g.

var x : Int? = nil
switch x {
case .Some( let value ):
    print("x has a value")
case .None:

In F#:

let x : int option = None
match x with
| Some(value) ->
    printfn "x has a value"
| None ->
    printfn "x is nil"

Currying

In my first look at the language, currying doesn’t seem quite as nice.
Here’s some F#:

let add a b = a + b
let add2 = add 2
let result = add2 3 // 5

In Swift (in the tersest way I know how at present) :

let add : (Int,Int) -> Int = { $0 + $1 }
let add2 = { add( 2, $0 ) }
let result = add2( 3 ) // 5

Another way (according to this) is to make the add function return a function like in the example below, but then doing a call to the initial function does not look like a standard function call:

func add (a:Int)(_ b:Int)-> Int {
    return a + b
}
add(2)(3) // not add(2,3) // 5
let add2 = add(2)
add2(3) // 5

Conclusion

This is a very shallow comparison. I just thought it was interesting.

F# tip: when app.config isn’t updated

0

A couple of times I’ve had the problem where changes to app.config were not reflected in my bin/Debug/MyApp.exe.config file. No amount of cleaning and rebuilding would cause the changes to take effect. The solution: delete the obj folder. Then a rebuild will have the latest changes.

F#, WPF, and Prism

0

I recently attempted to use F# to create a WPF project using the Prism MVVM library.  The project, if you want to download it or look at the code, is at https://github.com/mkb137/FSharpAndPrism.

Creating a WPF Application in F#

This isn’t too hard.  There’s no option to create an F# WPF application by default, but if you create an F# Console Application and then, in the project settings, flip it over to “Windows Application” it will run like one.

To get the WPF libraries, you have to add these references:
* PresentationCore
* PresentationFramework
* UIAutomationClient
* UIAutomationTypes
* WindowsBase
* System.Xaml

I used the FsXaml project to create usable F# types from WPF XAML files.
You can add vanilla XAML files, like App.xaml, with no backing class and then convert them to F# types via:

type App = XAML<"App.xaml", true>

Two things to be aware of:
1. All XAML files must be compiled as “Resource” (the default is None)
2. Visual Studio LIES.  As you may know, in F# the order of the files in solutions matter.  In F# projects, Visual Studio gives you “move up” and “move down” functions to put the files in order.  But once you start adding XAML files, all bets are off.  If you find the solution mysteriously failing to find libraries that it should, open your .fsproj file in a text editor and have a look at the included file order.  You may need to order it manually.

Adding Prism

I used the UnityBootstrapper, which in F# looks like this:

type Bootstrapper() =
    inherit UnityBootstrapper()
    override this.CreateShell() = 
        WindowUtils.loadComponent "/FSharpAndPrism;component/Shell.xaml"
    override this.InitializeShell() =
        base.InitializeShell()
        Application.Current.MainWindow <- ( this.Shell :?> Window )
        Application.Current.MainWindow.Show()
    override this.ConfigureContainer() =
        base.ConfigureContainer()
        this.Container.LoadConfiguration() |> ignore
        this.Container.RegisterInstance( this.Container ) |> ignore
    override this.ConfigureModuleCatalog() =
        base.ConfigureModuleCatalog()
        let moduleCatalog = this.ModuleCatalog :?> ModuleCatalog
        moduleCatalog.AddModule typedefof<AlphaModule> |> ignore

That WindowUtils.loadComponent is just a utility function to load the XAML resource:

module WindowUtils =
    let loadComponent( path ) =
    let resourceLocator = new Uri( path, UriKind.Relative )
    Application.LoadComponent( resourceLocator ) :?> DependencyObject

So I create a Shell with a MainRegion region…

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:prism="http://www.codeplex.com/prism"
    xmlns:infrastructure="clr-namespace:FSharpAndPrism.Infrastructure;assembly=FSharpAndPrism.Infrastructure"
    Title="F# Prism Demo" Height="150" Width="500"
    WindowStartupLocation="CenterScreen"
    >
    <StackPanel Orientation="Vertical">
        <Label Content="View Goes Here:"/>
        <ContentControl prism:RegionManager.RegionName="{x:Static infrastructure:RegionNames.MainRegion}"/>
    </StackPanel>
</Window>

And I create a view…

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Background="White"
    >
    <StackPanel Orientation="Horizontal">
        <Label>This is my view - Data context = </Label>
        <Label Content="{Binding}"/>
    </StackPanel>
</UserControl>

Register it as an F# type…

type MyView = XAML<"MyView.xaml",true>

And define a module that registers it with the region:

type AlphaModule( regionManager : IRegionManager, container : IUnityContainer ) =
    interface IModule with
        member this.Initialize() =
            regionManager.RegisterViewWithRegion( RegionNames.MainRegion, typedefof<MyView> ) |> ignore

And the result is… It doesn’t work.  The application runs but my view is not being loaded into the region.  Why?  Actually, with a little digging I find that the view is being loaded, it’s just not rendering.

FSharpAndPrism-Failure

FsXaml, Prism, and Unity

Problem #1 – Extra Constructor

As it turns out, when FsXaml creates a type derived from UserControl, in addition to UserControl’s void UserControl() constructor, FsXaml is adding a hidden void UserControl(FrameworkElement) constructor.  If the default configuration is not overridden, Unity will use this constructor when resolving the component and the type created with this constructor will not render itself correctly.  A simple but tedious way around this problem is to, for each view, register it with Unity so that the constructor taking no parameters is used.

container.RegisterType<MyView>( new InjectionConstructor() ) |> ignore

FSharpAndPrism-NoContext

Problem #2 – Adding a data context

Prism Views aren’t that useful with out their ViewModel data contexts and those are usually passed in the constructor.  So the first thing we want to do is subclass our the type that FsXaml created and add our own constructor.  This, by the way, solves our Unity problem as well since our subclassed type won’t have the bogus constructor that FsXaml is creating.
Here’s a basic view model type:

type MyViewModel() =
    let mutable name: string = null
    member this.Name
        with public get() = name
        and public set value = name <- value

Here’s our subclassed view (where the original has been renamed with a tick):

type MyView' = XAML<"MyView.xaml",true>

type MyView() =
    inherit MyView'()
    new( viewModel : MyViewModel ) as this =
        MyView()
        then
            this.DataContext <- viewModel

and… we have a problem.  By default, FsXaml derived types are sealed.  There’s no real reason for this other than that FsXaml is using a type provider from the fsprojects/FSharp.TypeProviders.StarterPack and it creates types as sealed for, I suppose, educational purposes.  If the “Sealed” attribute is removed from the created type it works fine.  I submitted a pull request to FsXaml who asked me to submit it upstream to FSharp.TypeProviders.StarterPack.  I submitted it a moment ago and haven’t heard back yet.  Until then, a “fixed” FsXaml implementation is at mkb137/FsXaml

Using the modified FsXaml library, it works and we have our view loaded with its data context:

FSharpAndPrism-WithDataContext

Final Problem: FSC: error FS2024: Static linking may not use assembly that targets different profile.

A normal WPF project is compiled against the .NET 4.5 profile which is known internally as Profile7 (see a list of PCL profiles here.  If you attempt to directly use any third-party library that is compiled not just for .NET 4.5, but for .NET 4.5 and Windows Phone (e.g. Profile78), you’ll get the error that you would never see in the same C# project:

FSC: error FS2024: Static linking may not use assembly that targets different profile.

And there’s no way around it as far as I know.  The bug has been logged here on F#’s current home on GitHub, and not yet fixed.

Functional programming with F#

0

In an episode of the .NET Rocks podcast, guest Bryan Hunter describes his experience analyzing a large object-oriented code base. It’s a good listen. The problems with it were the same problems you see with all large O-O code bases, he says. But one module was a complete surprise because…there were no problems. The application had zero downtime in 4 years of operation. The team was even able to do “hot loading” to deploy updates while the application was running. What was the difference? This module was written in Erlang, a functional language.

The life of a software engineer - cartoon

Life of a software engineer. I believe the original source is http://www.bonkersworld.net/building-software/

Whenever you build an enterprise-scale project, you will find yourself using a bare minimum of libraries and patterns such that despite your best intentions – or even because of your best intentions – your solution will be complex and tricky to maintain from moment one. It’s a terrible life we lead where following best practices feels bad and wrong. Functional programming may be the answer.

I’ve begun to learn .NET’s own functional programming language, F#. I wouldn’t call the language mainstream, but it’s not a toy, either. It’s completely compatible with the rest of the .NET class library so one can make WPF or ASP.NET MVC applications with it. I hope that it will one day lead to a more satisfying experience developing enterprise applications.

Some F# learning resources: