Category Archives: F#

Structural Equality – or is it?

I was recently presented with a conundrum. We had constrained data valid for the domain in a record type. Sadly this record type contained a reference datatype, so built-in structural equality broke down as the reference type never was equal in the way we thought would make sense.

This gave me the opportunity to learn how you override the implementation of Equals and GetHashCode in F# which I was previously unfamiliar with.

This is the finished implementation of the record type, or one like it, rather:

 [<CustomEquality>]
[<CustomComparison>]
type Structure =
{
Name: StructureName
Status: StructureStatus
Format: Regex
}
with
interface IComparable with
member this.CompareTo { Name = name; Status = status; Format = format } =
compare ( this.Name, this.Status, this.Format.ToString() ) (name, status, format.ToString())
interface IComparable with
member this.CompareTo obj =
match obj with
| null -> 1
| :? Structure as other -> (this :> IComparable<_>).CompareTo other
| _ -> invalidArg "obj" "not a Structure"
override this.Equals (o: obj) =
match o with
  | :? Structure as os ->
  (this.Name, this.Status, this.Format.ToString()) =
(os.Name, os.Status, os.Format.ToString())
| _ -> false
  override this.GetHashCode() =
  (this.Name, this.Status, thus.Format.ToString()).GetHashCode()

So yeah, ujse of pattern matching to determine data types in the non-generic functions and extensive use the built-in structural equality in tuples.

Very nice. With thanks to TeaDrivenDev and Isaac Abraham on Twitter (and this StackOverflow response)

Giraffe F# update

In a previous post I have written about Giraffe and shown some workarounds for what I perceived as limitations considering my existing enterprise ecosystem.

Now that Giraffe has turned 3.0 loads of things have improved even from my perspective. Obviously they are now competing in performance benchmarks, so loads of optimisation work has happened behind the scenes. For me, though – the most interesting bit is to see how they dealt with my complaints.

Configuration, logging and service location is now available through extension methods on the context.

Response handlers now handle streams and chunked responses.

Content negotiation looks very clean.

We have of course welcomed these improvements and use them in all our F# APIs.

The only remaining complaint is that the Swagger support is still not usable enough for our purposes. The fact that we would have to configure an additional separate nuget source onto get the package prevents us from actually using it in anger although showing API actions was simple enough but I’m unclear as to how to document request and response payloads – but that only becomes worth exploring when the package is served from nuget.org

More F# – Giraffe

So finally the opportunity arose to do some real world F# at work. Being involved in Enterprise Sofware Development a “real world” coding assignment is more akin to Enterprise FizzBuzz than cool Data Science. A colleague had had earlier success using Giraffe, so I favoured that for this task and this blog post is a charting of my struggles. I needed to create an API to server a specfic type of files and non-functional requirements were that I needed to support an existing deployment pipeline for various environments that currently rely on configuration using appSettings.json as well as logging to Serilog and additionally I need OIDC support to authenticate between services. Finally – of course – I need to store data in old school SQL Server.  Ideally, I would have liked to provide a Swagger page which I could point to when I want front-end peeps to RTFM, but that is not supported, so I’ll have to tell them to use the source.

Getting started

In order to get off the ground I installed VS Code with Ionide using the getting started guide. I already had .NET Core 2.0 installed, so I could just use dotnet new to create a F# Giraffe scaffold.

Configuration

In order to set up the correct Identity Server parameters I needed this web site to support configuration, and I already knew I wanted to use bog standard ASP.NET Core configuration (including inheritance – yes, I need it. No it’s not worth the effort to change the circumstances) rather than fancier stuff like yml, the best config markup available. Yes, I could save the world by building a config provider for yml and update all our configs, but today is not that couple of weeks that would take to land a change of that magnitude.

.NET Core 2.0 for n00bs

Oh, yes, I forgot to mention – this is my first outing on .NET Core 2.0, so there are a couple of changes you notice in the hosting and app configuration pipeline. One of them is I don’t know where my configuration is supposed to live. Or rather, it can live where it used to live, in the Startup class, but the startup class is now optional, as you have other calls on the host builder that can let you configure app configuration and logging without needing a startup class. For my purposes that was a no go, I needed to get hold of my configuration somehow, so I created a startup class and created a singleton to hold the complete configuration. This singleton got initialised when the startup class was created. With this I could now configure authentication. This isn’t the nicest way to do things, and I’m open to better ideas, but google had nothing. It was as if I was the first one ever to attempt this, which is partially why I’m writing this down. If I’m wrong, hopefully somebody will give me snark about it so I can update with a corrected version.

Authentication

There is a sample for how to use JwtBearerToken authentication, so I just used my new-found configuration skills to add a layer of usefulness to it. Essentially in the jwtBearerOptions function I get the config singleton from above and I use

  configMgr.GetSection("JwtBearerOptions").Bind(cfg);

to bind the configuration file settings to the object and afterwards I set some defaults that I don’t want to be configurable. To my shock, I ran postman and sent a valid token to the claims Giraffe sample endpoint and I got me some claims. Incredibly, it worked.

Database access

I have, in C#, come to enjoy Dapper. No nonsense, you write the queries, you get the data sort of lightweight ORM that is simply enjoyable to use. I found an F# wrapper over Dapper that Just Worked. Asked my config singleton for the connection string and we were off and running. Most enjoyable. There were some gotchas involving querying with GUIDs, which I circumvented by typecasting, as in

WHERE CONVERT(varchar(60), FieldA) = @FieldA

I assume you have to cast in your selects the other way around to query uniqueidentifiers as well. but that’s not the worst thing in the world.

Also, multiple parameters in a map to the F# wrapper means you have to cast the variables to obj before you call the query method.

 Map [ "FieldA", fieldA :> obj; "FieldB", fieldB :> obj]

Serving files

I made a tiny hack to serve binaries:

let stream (streamInstance : Stream) : HttpHandler =
    fun (next : HttpFunc) (ctx : HttpContext) ->
    task {
        ctx.Response.Headers.["Content-Type"] <- StringValues("application/pdf")
        ctx.Response.Headers.["Content-Length"] <- StringValues(streamInstance.Length.ToString())
        do! streamInstance.CopyToAsync(ctx.Response.Body)
        return Some ctx
    }

Of  course, a proper implementation will have some kind of record type or at least tuple to provide the mime type with the stream rather than hardcode it.

Service Locator

I set up the IoC container in my unsuccessful attempt at getting Swashbuckle to document the API. I registered an operation filter I normally use to make Swagger ask for an authorisation header on API operations that require it, and that was a bit fiddly, but not very weird. I just made a module that gets called from the ConfigureServices method in the startup class.

Conclusion

Yes, loads of classes and mutable methods. This really is a mess from an F# perspective. Not a lot of tail recursion and immutability. I put the blame on ASP.NET Core. And also I suck at F#, although I’m trying.. My hope is that once this is done I can revise and do better. No, I can’t show you teh codez, but suffice it to say, it looks a lot like the above sample code.

 

 

 

 

Red mist

Sometimes you get so upset about something you need to blog about it, and ranting on Twitter, Facebook and Channel 9 comments just did not quite seem enough.

The insult, and the injury

I watched a Channel 9 talk about the “future of C# and VB” by Jay Schmeltzer from DEVintersection where he went over the future of the .NET stack, and started out by looking over the Stack Overflow statistics of programming languages that I have addressed before. He showed the graph of Most Popular Technologies showing C# placed prominently fourth behind Java, SQL and JavaScript, then Jay showed the category Most Loved languages, where Microsoft  have a runaway hit with F# on third place, and then C# way down on 10th place. Obviously, VB was right on top of the Most Feared, but that you knew already. Jay expressed much pride in having C# all the way up on 10th of most loved languages and then said “and we have Microsoft’s F# up here on 3rd, but that is of course more of a … well,  C# is of course mainstream in a different way”. So in other words, not even a pretence that F# is a first class citizen in .NET.

Contrast with Apple. From almost single handed creating Objective C into something that is in existence and popular despite the crushing superiority in funding and mindshare of C++ – Apple basically told everybody that (the F# clone) Swift is it from now on. They basically did a VB6 -> C# sort of story, telling everybody that they were welcome to use that old stuff but they really should get on board with the modern technologies.

Contrast that with the above statement from top brass at Microsoft.

So basically, in this blog I am trying to collect ways which a dark matter C# developer can just start using F# today thanks to the extremely ambitious efforts of the friendly and hard-working F# community, and show to the extreme extent Microsoft isn’t bothering at all – ignoring the goldmine they are sitting on. I’m trying to find ways which make things easier for existing Microsoft-focused developers, so I will be collating the things you can use to go F# today for the crummy ASP.NET LOB apps that make up the bread and butter of the C# world.

The comeback

My goal is providing ways which you can go F# today, and immediately write less code with fewer bugs that do the things your C# code does today. You will eventually discover cooler things, like package management using Paket (wich support Nuget package streams and maintaining dependencies directly from GitHub or similar) amd the very F# web framework Suave.io and using FAKE as a build system rather than MSBuild, which helps if you have complex builds where you would like to not mess with XML and rather read F# code. You may perhaps find other ways to persist data that are more natural to use in F# and you will have little problem learning them once you get over the hump, but just to make the barrier to entry extremely low, let’s keep things familiar and non-scary. The things that would come for free if Microsoft had devoted more than a fraction of means towards F# in Visual Studio is the templating that makes C# so easy to use when creating websites and web services. To achieve that ease-of-use we have to rely on the community, and they have despite the odds come up with a few competitive options over the years. I have compiled these on my F# for C# people page which I hope to keep updated.

Desktop OS for developers

The results of the latest StackOverflow Developer Survey just came out, showing – among other interesting things – that Windows is dying as a developer OS. Not one to abandon ship any time soon I’d still like to offer up some suggestions.

TL;DR

  • Make the commandline deterministic.
  • Copying files across the network cannot be a lottery.
  • Stop rebooting UI-frameworks
  • Make F# the flagship language

Back in the day, Microsoft through VB and Visual C++ overcame some of the hurdles of developing software for Windows – then the only, effectively, desktop OS in the enterprise. Developers, and their managers, rallied behind these products and several million kilometres of code was written over a couple of decades.

The hurdles that were overcome were related to the boilerplate needed to register window classes, creating a window and responding to the basic window messages required to show the window in Windows and have the program behave as expected vis-a-vis the expectations a Windows user might have. Nowhere in VB6 samples was anybody discussing how to write tests or how, really, to write good code. In fact, sample code, simplified on purpose to only showcase one feature at a time, would not contain any distractions such as test code.

When Classic ASP was created, a lot of this philosophy came a cross to the web, and Microsoft managed to create something as horrible as PHP, but with less features, telling a bunch of people that it’s OK to be a cowboy.

When the .NET framework was created as a response to Java, a lot of VB6 and ASP.NET  programmers came across and I think Microsoft started to see what they had created. Things like Patterns & Practices came out and the certification programmes were taking software design and testing into consideration. Sadly, however, they tended to give poor advice that was only marginally better than what was out there in the wild.

Missed the boat on civilised software development

It was a shock to the system when the ALT.NET movement came out and started to bring in things that were completely mainstream in the Java community but almost esoteric in .NET. Continuous integration – unit testing – TDD – DDD. Microsoft tried to keep up by creating TFS that apart from source code version in had ALM tools to manage bugs and features as well as a built-in build server but it became clear to more and more developers that Microsoft really didn’t understand the whole thing about testing first or how lean software development needs to happen.

While Apple had used their iron fist to force people to dump Mac OS for the completely different, Unix-based operating system OS X (with large bits of NextStep brought across, like the API and InterfaceBuilder) – Microsoft were considering their enterprise customers and never made a clean break with Gdi32. Longhorn was supposed to solve everything, making WPF native and super fast, obsoleting the old BitBlt malarkey and instead ushering in a brighter future.

As you are probably aware, this never happened. .NET code in the kernel was a horrible idea and the OS division banned .NET from anything ever being shipped with Windows, salvaged whatever they could duct tape together – and the result of that was Vista. Yes, .NET was banned from Windows and stayed banned up until Powershell became mainstream a long, long time later. Now, with Universal Windows Apps, a potentially viable combo of C++ code and vector UI has finally been introduced, but since it is the fifth complete UI stack reboot since Longhorn folded, it is probably too little too late and too many previously enthusiastic Silverlight or WPF people have already fallen by the wayside. Oh and many of the new APIs are still really hard to write tests around, and it is easy finding yourself in a situation where you need to install Visual Studio and some SDK on a build server, because the dependency relies on the Registry or the GAC rather than things that come with the source.

Automation

As Jeffrey Snover mentions in several talks, Windows wasn’t really designed with automation in mind. OLE Automation possibly, but scripting? Nooo. Now, with more grown-up ways of developing software – automation becomes more critical. The Windows world has developed alternate ways of deploying software to end-user machines than work quite well, but for things like automated integration tests and build automation you should still be able to rely on scripting to set things up.

This is where Windows really lets the developer community down. Simple operations in Windows aren’t deterministic. For a large majority of things you call on the command-line  – you are the only one responsible for determining if the command ran successfully. The program you called from the command-line may very well have failed despite it returning a 0 exit code. The execution just might not have finished despite the process having ended, so some files may still be locked. For a while, you never know. Oh, and mounting network drives is magic and often fails for no reason.

End result

Some people leave for Mac because everything just works, if you can live with bad security practices  and sometimes a long delay before you get some things like Java updates. Some people leave for Linux because if you script everything, you don’t really mind all those times you have to reinstall because thing like a change in screen resolution or a security update killed the OS to the point you can’t log in anymore, you just throw away the partition and rerun the scripts. Also, from a developer standpoint, everything just works, in terms of available tools and frameworks.

What to do about it

If Microsoft wants to keep making developer tools and frameworks, they need to start listening to the developers that engage whenever Microsoft open sources things. They most likely have valuable input into how things are used by your serious users – beyond the tutorials.

Stop spending resources duplicating things already existing for Windows or .NET as that strikes precisely at the enthusiasts that Microsoft needs in order to stop hemorrhaging developers.

What is .NET Core – really? Stop rewriting the same things over and over. At least solve the problems the rewrite was supposed to address first before adding fluff. Also – giving people the ability to work cross-platform means people will, so you are sabotaging yourselves while building some good-will, admittedly.

Most importantly – treat F# like Apple treats Swift. Something like – we don’t hate C# – there is a lot of legacy there but F# is new, trendier and better. F# is far better than Swift and has been used in high spec applications for nine years already. Still Microsoft after years of beta testing still manages to release a JITer that has broken tail call optimisation (a cornerstone of functional runtimes as it lets you do recursion effectively). That is simply UNACCEPTABLE and I would have publicly shamed then fired so many managers for letting that happen. Microsoft needs to take F# seriously – ensure it gets the best possible performance, tooling and templating. It is a golden opportunity to separate professional developers from the morons you find if you google “asp.net login form” or similar.

In other words – there are many simple things Microsoft could do to turn the tide, but Im not sure they will manage, despite the huge strides taken of late. It is also evident that developers hold a grudge for ages.

F# puzzle

One of my colleagues at Jayway launched a functional puzzle and solicited responses via Github gists. The challenge was as follows:

  1. Write a function that, given a sequence of either positive or negative integers, returns true if any subset of the list sums up to zero. Eg:
    find-solutions ([-7 4 3 8 -5]) => true
    find-solutions ([-6 2 3]) => false
  2. Make it work with any number, not just zero. Eg:
    find-solutions (0, [-7 4 3 8 -5]) => true
    find-solutions (13, [-7 4 3 8 -5]) => false
  3. Make it return all matching sequences, instead of a boolean. Eg:
    find-solutions (0, [-7 4 3 8 -5]) => [ [-7 4 3] [-7 4 8 -5] ]
    find-solutions (13, [-7 4 3 8 -5]) => []
  4. Make it take any predicate for the sum, not just equal to a number. Eg:
    find-solutions (isZero, [-7 4 3 8 -5]) => [ [-7 4 3] [-7 4 8 -5] ]
    find-solutions (isOdd, [-7 4 3]) => [ [-7] [3] [-7 4] [4 3] ]

Of course, me being an F# n00b I ended up at StackOverflow within hours of trying my hand at this, and I also asked among code monkeys on Facebook,  so I will not submit an answer is it wouldn’t be my own. My colleagues went ahead and figured out solutions on their own rather than use Google engineering like I did.

Anyway, as you can imagine, the first bit is the hard one. With higher order functions, delegating the actual filtering is done easily thereafter by supplying  the comparer function as a parameter.

So what do you do? I looked at many solutions, but couldn’t manage to use the comme il faut solution with a permutation tree, but went with a list of permutations instead which I then could trivially recurse through to see if I ever find a match.

If you are using Google engineering to solve F# problems, be aware that the old function Seq.map_concat has been renamed Seq.collect, which is a clear improvement.

In my case I found my permutation function on StackOverflow, provided by the excellent Tomáš Petříček, see blogroll, and just added my c0dez to find matches. This is from a console app, so hence the EntryPoint business.

let rec permutations list taken = 
  seq { if Set.count taken = List.length list then yield [] else
        for l in list do
          if not (Set.contains l taken) then 
            for perm in permutations list (Set.add l taken)  do
              yield l::perm }

let rec isMakingZero acc lst =
    match lst with
     | [] -> false
     | a :: tail -> (acc + a = 0) || isMakingZero (acc + a) tail 
    

let rec testpaths pathlist =
    if Seq.length pathlist = 0 then
        false
    else
        isMakingZero 0 (Seq.head pathlist) || testpaths (Seq.skip 1 pathlist)

[<EntryPoint>]
let main argv = 
    printfn "First %A"  (testpaths (permutations [1; -2; 3; -5] Set.empty))
    printfn "Second %A" (testpaths (permutations [1; -3; 2; -5] Set.empty))
    0 // return an integer exit code

    

As you can imagine, you just supply a function to testpaths that then gets passed down to isMakingZero, which should be renamed, in order to solve the remaining tasks.