Fork me on GitHub

I am pleased and honored to announce that I will be a speaker at this years F# eXchange 2017 conference.

F# Community

It’s almost 3 years ago since I became acquainted with Skills Matter and the F# Community. I had spoken previously with Phillip Trelford because I have co-founded the F#unctional Copenhageners Meetup Group, which is like a sisterhood to F#unctional Londoners Meetup Group. In another case, due to work with Microsoft Dynamics CRM, I had come across Ross McKinlay (I still owe you some beers). Both were present at the Meetup.

When I arrived to the venue, I bumped into Don Syme at the door. I was really not expecting that. Rob Lyndon talk started and I was amazed how this punk rocker, with a Mohawk, looking guy absolutely mastered coding GPU kernels type-safely in F#. It was pretty amazing.

After the Meetup, we all went over and had a beer (or many) at a near bar. This was great as it gave the possibility to meet many of the people who did incredible work for the Community. I specially noticed Tomas Petricek, due to the amazing tools that he has provided and which I have used have used professionally: F# Formatting, F# Data, among others.

I think it was the night that The Don agreed to give a talk at MF#K as he would be in Copenhagen due to some ICFP related work. His talk is still one of the most attended and I would argue that it was the cornerstone to the foundation of our Meetup group when we are about to reach 700 members where the next upcoming talk we are hosting, will be having 2 × F# MVPs on stage.

Time has passed, and MF#K have hosted a variety of functional programming languages talks, most of them F# related, and I have personally given around a dozen of F# talks and some 1-day courses. I recently held my very first international abroad talk in Sweden (Malmö) to restart SweNUG, the Swedish .NET User Group, and my very last talk might derive in a an official F# project.

Note: Oskar, sorry for not being able to work on the project at the moment.

F# eXchange 2017 Conference

That’s why I write that I am honored to give a little back to F# Community which have given me so much.

In addition to greet old acquaintances, I am really pleased and looking forward to the strong program that has been put together:

  • I had the pleasure to see this year’s Conference Keynote, Evelina, at NDC London last year. She is an incredibly facilitator that captures the attention of everyone attending the talk. Besides her unquestionable knowledge, she is also very hands on, key component that many forget when giving a talk. It also helps that she chooses topics which seems interesting for most of us.

  • Scott Wlaschin is without any doubt, one of my favorite people in the F# community. He has one of the best learning sources, if not the best, he an incredible communicator who is able to teach very complex theory with analogies that most understand. Just an example Railway Oriented Programming.

  • I’m really looking forward to meet Michael Newton. I Have read time and time again his blog post on the subject of Type Providers and learned a lot from them, to the degree that it helped immensely to create one professionally DAXIF. Now, I can finally put a face to the blog.

  • Last but not least, my fellow paisano Alfonso Garcia-Caro who in collaboration with ncave have made a fantastic job on Fable. Really looking forward to his talk and maybe some discussion with regard of the Motherland over a few beers.

To all the speakers I do not mention, it’s because I do not know your work but I am really looking forward to your talks !!!

The only cons I have noticed so far with regard of the conference is that there are some cases where I would really like to see both talks scheduled at the same time. But I guess that’s what happens when a conference starts getting bigger. Kudos Skills Matter.

Here is the title and abstract of my talk. I hope you will enjoy it and hopefully, nobody will be disappointed:

Puritas, A journey of a thousand miles towards side-effect free code

Puritas, from Latin, means linguistic correctness, from a lexical point of view.

In this talk, you will be exploring and walking down the bumpy road of trying to bring side-effect free code to F#. The journey started, in Ramon’s case, a few years ago while working for an IT consultancy company where Ramon made: Delegate.Sandbox, a library providing a Computation Expression named SandboxBuilder, sandbox { return 42 }, which ensures that values returned from the computation are I/O side-effects safe. The library is built-on top of .NETs Partially Trusted Code Sandboxes. The path of exploration somehow stalled.

Now with new ideas under the hood and great tooling provided by Microsoft and the amazing F# Community, the journey continues towards bringing this missed feature to an already brilliant and loved programming language, that is used by thousands in the magnitude of 4.

Hopefully one day, the reserved keyword: pure (The Holy Grail of F# keywords) will be claimed, and we will be able to use it with ease as we do with other keywords such as: seq, async, query, lazy and so on.

Link: F# eXchange 2017 full 2-days programme

Code Snippet

1
2
3
4
5
6
7
8
9
10
11
type ``{0}  <0xFFFFFFFF`` = uint32
type ``ℤ∗<0xFFFFFFFF`` = uint32

let ``42`` : ``{0} <0xFFFFFFFF`` = 42u

let add : ``ℤ∗<0xFFFFFFFF`` -> ``ℤ∗<0xFFFFFFFF`` -> ``ℤ∗<0xFFFFFFFF`` =
fun x y ->
x + y

let result1 = ``42``
let result2 = add 42u 42u

Code output:

> type {0} ∪ ℕ<0xFFFFFFFF = uint32
> type ℤ∗<0xFFFFFFFF = uint32
> val 42 : {0} ∪ ℕ<0xFFFFFFFF = 42u
> val add : x:ℤ∗<0xFFFFFFFF -> y:ℤ∗<0xFFFFFFFF -> ℤ∗<0xFFFFFFFF
> val result1 : {0} ∪ ℕ<0xFFFFFFFF = 42u
> val result2 : ℤ∗<0xFFFFFFFF = 84u

References:

Code Snippet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
module Standard =
let (@@) : ('a -> 'b option) -> ('a -> 'b option) -> 'a -> 'b option =
fun f g x ->
match f x with
| None -> g x
| some -> some

let standard : string -> string option = function
| ".txt" -> Some "text/plain"
| ______ -> None

type config =
{ mimeTypes : string -> string option }

let patternMatch : string -> config -> string option =
fun x { config.mimeTypes = f } ->
f x

let config = { mimeTypes = standard }

module Custom =
open Standard

let extended : string -> string option = function
| ".avi" -> Some "video/avi"
| ______ -> None

let custom = standard @@ extended

let config = { config with mimeTypes = custom }

Standard . config |> Standard . patternMatch ".avi"
Custom . config |> Standard . patternMatch ".avi"

Code output:

> 
module Standard = begin
val ( @@ ) : f:('a -> 'b option) -> g:('a -> 'b option) -> x:'a -> 'b option
val standard : _arg1:string -> string option
type config =
{mimeTypes: string -> string option;}
val patternMatch : x:string -> config -> string option
val config : config = {mimeTypes = <fun:config@19>;}
end

>
module Custom = begin
val extended : _arg1:string -> string option
val custom : (string -> string option)
val config : Standard.config = {mimeTypes = <fun:custom@28-2>;}
end

> val it : string option = None
> val it : string option = Some "video/avi"

References:

F# Advent Calendar 2016

This post is part of the F# Advent Calendar in English 2016. Please check out the other posts as well.

I would also like to thank Scott Wlaschin for his willingness to make an e-book with the posts and raise money for a good cause: Tweet. Be sure to contribute with this cause (retweet and economically).

Background

It should be no secret that I’m a big fan of Elm and it shouldn’t be no secret as well that I have been working with F# for a long time and is still a bit of a fanboy.

One of the features that is missed the most when jumping between these two fantastic languages is the Semantic Versioning to handle package versions from Elm (bump and diff).

In this blog post I will argue that I have made a .NET library (very early in development stage but almost complete, you folks will decide) that will be able to help you out whenever you have to decide if a new version of your Assembly or NuGet package is a Major, Minor or just a Patch (Major.Minor.Patch).

Semantic Versioning

So what is Semantic Versioning (SemVer)? If we look into the following website: semver.org, we can read statements like:

  • In the world of software management there exists a dread place called “dependency hell”.

  • The bigger your system grows and the more packages you integrate into your software, the more likely you are to find yourself in it.

  • If dependencies are specified too loosely, you will probably end up breaking your build more than desired.

In the mentioned website there are described 12 rules, to be enforced by documentation or the code itself, to solve the issue but we will stay with the following summary:

  • … given a version number (MAJOR.MINOR.PATCH), increment the:

    • MAJOR version when you make incompatible API changes,

    • MINOR version when you add functionality in a backwards-compatible manner, and

    • PATCH version when you make backwards-compatible bug fixes

And that is pretty much it.

Note: I have removed the word documentation, as I am in the belief that this task should be done automatically by a computer and not by a human. In a similar way as a computer help us catch errors at compile time instead of end-users at runtime.

elm-package bump and diff

If we look into Elm’s tool for package publishing, called elm-package, it has two main actions which are related to SemVer: bump and diff

elm-package bump

As we can see from the GitHub repository of the tool, the version rules as very similar to the ones we just described in the previous section:

  • Versions all have exactly three parts: MAJOR.MINOR.PATCH

  • All packages start with initial version 1.0.0

  • Versions are incremented based on how the API changes:
    • PATCH - the API is the same, no risk of breaking code ✓
    • MINOR - values have been added, existing values are unchanged ✓
    • MAJOR - existing values have been changed or removed ✓
  • elm-package will bump versions for you, automatically enforcing these rules ✓✓✓

Note: You can’t actually publish a package without running the bump action first.

elm-package diff

The previous action, bump is really good to tell the hole world (broadcast) the changes you have done to your library, while, diff, is great for a consumer of a library to actually see which changes have been made and if they are actually going to have an impact on the library they are developing. Example, if changes are done to some data structures I’m not using, I would probably be able to just upgrade to the newer version without having to refactor any code:

Rust and others

Other languages have been looking into SemVer as well:

I think we all have tried to use a given package that failed to install due to issues with dependent packages right? Frustration, most of the time, tend to dropping a given package and sometimes even moving on to other languages …

SpiseMisu.SemanticVersioning library

Here is my proposal of SemVer for .NET libraries as well as for NuGet packages

Note: I support both C#/F# (VB? I’m not the right guy to do this task …)

As with Elm, I would like the rules to be enforcement by the code itself, instead of by humans. Otherwise we would be back to square one as humans tend to fail with repetitive task and when the library becomes of a considerable size, the task will become unmanageable.

Elm has it easy as everything is Open Source, therefore source code can be parsed while with .NET (proprietary libraries) we will have to fallback to handle this task just like Unit Tests are handled in Fsharp.Core with Reflection:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
asm.GetExportedTypes()
...

(* extract canonical string form for every public member of every type *)
seq {
yield!
t.GetRuntimeEvents()
|> Seq.filter (fun m -> m.AddMethod.IsPublic)
|> Seq.map cast
yield!
t.GetRuntimeProperties()
|> Seq.filter (fun m -> m.GetMethod.IsPublic)
|> Seq.map cast
yield!
t.GetRuntimeMethods()
|> Seq.filter (fun m -> m.IsPublic)
|> Seq.map cast
yield!
t.GetRuntimeFields()
|> Seq.filter (fun m -> m.IsPublic)
|> Seq.map cast
yield!
ti.DeclaredConstructors
|> Seq.filter (fun m -> m.IsPublic)
|> Seq.map cast
yield!
ti.DeclaredNestedTypes
|> Seq.filter (fun ty -> ty.IsNestedPublic)
|> Seq.map cast
} |> Array.ofSeq

There is a bit more to it as the main issue with basic Reflection, is that it works great with C# libraries, but not so much with F#. The following functions signatures are represented on the same way in .NET canonical form (no curried arguments):

1
2
3
4
5
6
7
8
9
let foo (x,y) = x + y
let bar x y = x + y

(* both represented as *)
x:System.Int32 * y:System.Int32 -> z:System.Int32

(* but should be respectively *)
x:System.Int32 * y:System.Int32 -> z:System.Int32
x:System.Int32 -> y:System.Int32 -> z:System.Int32

Therefore we need to have in mind a few other cases such as Product Types, Modules and even Enums & Sum Types (due to pattern matching) that needs to be handled in a special way:

  • Cases like Active/Partial Patterns and MeasureOfUnits are not handled (yet? Is it even necessary?).

  • Please look into the Open Source code to see what is done for each cases.

The main goal is to create a bijective function that would replace the non-injective and surjective function which will ensure that a given input value will always have a unique output value. Think of it as a perfect hash function with no collisions.

I’m also becoming really keen to Haskell and Elm signatures readability, where the last type is the return type of the function while the others are input parameters. Example:

1
FooBar : Foo -> (Bar * Baz) -> Qux

This is also the reason why I have begun to write F# code like this:

1
2
let foobar : int -> (int * int) -> int =
fun x (y,z) -> x + y + z

And therefore I’m aiming to produce output that comply with these signatures.

Note: The learning curve for F# would be non-existent as we already see this kind of signatures when evaluating with F# Interactive but it might be hard, at the beginning, to read for the C# Community, but they probably get used to it.

As mentioned in the title, I’m aiming to support both Assemblies and NuGet packages:

  • .NET Library (Assembly): Is usually a single file compiled to target a specific version of the .NET Framework. Example:
mscorlib,Version=4.0.0.0, Culture=neutral,PublicKeyToken=...
  • .NET NuGet package: Is a unit of distribution containing some metadata as well as binaries. In most cases, there are binaries targeting several versions of the .NET Framework. We are only interested in libraries (lib/…/???.dll)

Here are a few examples on the usage of the library:

.NET NuGet package

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/usr/bin/env fsharpi

#I @"./SpiseMisu.SemanticVersioning/"
#r @"SpiseMisu.SemanticVersioning.dll"

open System
open System.Diagnostics
open System.Reflection

open SpiseMisu

let pkgid = @"Newtonsoft.Json"

let assembly =
Assembly.LoadFile
@"./packages/Newtonsoft.Json.7.0.1/lib/net45/Newtonsoft.Json.dll"

Semantic.Versioning.nugetbump
pkgid
NuGet.dotNet.Net45
assembly
|> printfn "%s"

Semantic.Versioning.nugetdiff
pkgid
NuGet.dotNet.Net45
(Some "7.0.1")
pkgid
NuGet.dotNet.Net45
None
|> Array.iter(printfn "%s")

Output Gist SpiseMisu.NuGet.SemVer.md

.NET Library (Assembly)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/env fsharpi

#I @"./SpiseMisu.SemanticVersioning/"
#r @"SpiseMisu.SemanticVersioning.dll"

open System
open System.Diagnostics
open System.Reflection

open SpiseMisu

let released =
Assembly.LoadFile
@"./packages/Newtonsoft.Json/lib/net45/Newtonsoft.Json.dll"
let modified =
Assembly.LoadFile
@"./packages/Newtonsoft.Json.7.0.1/lib/net45/Newtonsoft.Json.dll"

Semantic.Versioning.asmbump released modified
|> printfn "%s"

Semantic.Versioning.asmdiff released modified
|> Array.iter(printfn "%s")

Output Gist SpiseMisu.Assembly.SemVer.md

.NET Library (documentation)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/env fsharpi

#I @"./SpiseMisu.SemanticVersioning/"
#r @"SpiseMisu.SemanticVersioning.dll"

open System
open System.Diagnostics
open System.Reflection

open SpiseMisu

let assembly =
Assembly.LoadFile
@"./packages/Newtonsoft.Json/lib/net45/Newtonsoft.Json.dll"

Semantic.Versioning.markdown assembly
|> Array.iter(printfn "%s")

Output Gist SpiseMisu.Docs.SemVer.md

Note: A side-effect of the code is that I was actually able to document the hole public API of a given library. Therefore I thought that I would just expose this logic, this was not intentional.

.NET Library (raw)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/env fsharpi

#I @"./SpiseMisu.SemanticVersioning/"
#r @"SpiseMisu.SemanticVersioning.dll"

open System
open System.Diagnostics
open System.Reflection

open SpiseMisu

let assembly =
Assembly.LoadFile
@"./packages/Newtonsoft.Json/lib/net45/Newtonsoft.Json.dll"

Semantic.Versioning.raw assembly
|> Set.toArray
|> Array.iter(fun (prefix, body) -> printfn "%s - %s" prefix body)

Output Gist SpiseMisu.Raw.SemVer.txt

Note: I have decided that my output should be of the type of Markdown, if other should differ from this opinion, they can just work with the raw data and produce their own.

Trivial Pursuit

Just to have an understanding of what is going on under the hood. Lets take a look at the following example code:

Enum.cs

1
2
3
4
5
6
7
8
namespace SpiseMisu
{
public enum Enum
{
Foo=0,
Bar=42
}
}

Enum2.cs

1
2
3
4
5
6
7
8
namespace SpiseMisu
{
public enum Enum
{
Foo=42,
Bar=0
}
}

Enum3.cs

1
2
3
4
5
6
7
8
9
10
namespace SpiseMisu
{
public enum Enum
{
Foo=0,
Bar=42,
Baz=4,
Qux=2
}
}

which is compiled with Mono producing .NET assemblies.

1
2
3
4
5
6
7
8
9
10
#!/bin/bash

for f in src/*.cs
do
name=${f##*/}
if [ ${name%.*} != "AssemblyInfo" ] ; then
echo "Compiling:" $f
mcs -target:library -out:"./lib/"${name%.*}".dll" $f "./src/AssemblyInfo.cs"
fi
done

We will now compare the Enum.cs vs Enum2.cs and Enum.cs vs Enum3.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/usr/bin/env fsharpi

#I @"./SpiseMisu.SemanticVersioning/"
#r @"SpiseMisu.SemanticVersioning.dll"

open System
open System.Diagnostics
open System.Reflection

open SpiseMisu

let asm1 =
Assembly.LoadFile
@"./lib/Enum.dll"
let asm2 =
Assembly.LoadFile
@"./lib/Enum2.dll"
let asm3 =
Assembly.LoadFile
@"./lib/Enum3.dll"

Semantic.Versioning.asmbump asm1 asm2
|> printfn "%s"

Semantic.Versioning.asmdiff asm1 asm2
|> Array.iter(printfn "%s")

Semantic.Versioning.asmbump asm1 asm3
|> printfn "%s"

Semantic.Versioning.asmdiff asm1 asm3
|> Array.iter(printfn "%s")

What is the outcome that you expect?

Output Gist SpiseMisu.Talk.SemVer.md

If you guessed that it should be a MAJOR update in both cases, then you are actually right. I’m one of those guys that always compile my F# code with the following flag: –warnaserror:25 to ensure that all patterns are covered. Therefore, if you add a new value to Enums and Sum Types, this should state that is a MAJOR update and you should probably revise your code to handle the newly added patterns.

What’s next?

I have given a talk on this matter at MF#K where we had an interesting discussion (a few feature addition were requested). I will see how fast I can make these changes and finalize the project, based on Project Scaffold, and then I will release the library as Open Source @ GitHub.

When the code is publicly available, I would RFC from the .NET Community, specially experts in the subject, to review the code.

Note: Have in mind, that I’m not using the F# Compiler Services as I’m aiming for a very lightweight library with as few dependencies as possible

The outcome I desire for this library is that it gets integrated with:

  • NuGet: Or something similar, please steal with pride. The goal is that we get this awesome feature and not so much that it was me who did it.

  • FAKE: This is one of the reasons I produce Markdown output as it is possible to just pipe the result of bump and diff to the top of the RELEASE_NOTES.md to automate the generation of this document, as it sometimes can be a bit tedious and boring.

  • Paket: This would be optional, but because this tool already has NuGet package publishing capabilities, therefore it would give sense to add the bump and diff functionality.

Last, but not least, in order to catch on with the C# Community, I guess that we will need a standalone executable (something like paket.exe) which is totally transparent with regard of it’s F# nature, as we all know some .NET people are allergic to the this amazing programming language. I’m thinking about using for this task:

Conclusion:

I hope I’ve convinced you of why SemVer enforced by code is so awesome.

I’m also hopping that you can agree that the presented library:

  • Supports .NET Assemblies and NuGet packages as well as C# and F# (even proprietary due to Reflection).

  • SemVer rules are also enforced by the code itself, just like elm-package.

  • The produced Markdown output is easily readable.

As I mentioned before, I gave a talk on the subject at the F#unctional Copenhageners Meetup Group where we had a really constructive discussion with different points. One of the main points, delivered by Ulrik Rasmussen was that Semantic Versioning shouldn’t be called that in the first place, but instead it should be called Syntactic Versioning as we are only able to see if a dependencies break when signatures change (syntax) and not if the behavior (semantics) change. Let’s look into a simple example where we just refactor our foo function from fold left with right:

1
2
3
4
5
let foo : int list -> int list =
fun xs -> List.fold(fun a x -> x :: a) [] xs

let foo : int list -> int list =
fun xs -> List.foldBack(fun x a -> x :: a) xs []

Syntactically the signatures are the same, but the semantics of the application aren’t.

That said, I think the intentions of Tom Preston-Werner was to keep the dependency hell to a minimum as well as limiting the amount of builds breaking. As with everything else, there is really no silver bullet to solve all our problems at once, but we should strive to achieve it though:

Perfection is not attainable, but if we chase perfection we can catch excellence” –Vince Lombardi

Code Snippet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
-- HELPERS


isHex : String -> String
isHex str =
case String.startsWith "0x" str of
True ->
hexToString (String.dropLeft 2 str)

False ->
toSingleByte str


hexToString : String -> String
hexToString hex =
-- Take chunks of 2 hex digits and apply formula: (a * 16^1) + (b * 16^0)
-- Example (d_16 = 13_10): 0xd3 => (d * 16^1) + (3 * 16^0) = 208 + 3 = 211
let
zero =
hex |> String.all (\c -> c == '0')

asciiToNumber x =
let
y =
x |> Char.toCode
in
case y > 96 of
-- ASCII codes for [a-f] => [97-102]
True ->
y - 97 + 10

-- ASCII codes for [0-9] => [48-57]
False ->
y - 48

rec xs acc =
case xs == "" of
False ->
let
( y, ys ) =
case String.uncons xs of
Nothing ->
( Nothing, "" )

Just ( a, rest ) ->
( Just a, rest )

( z, zs ) =
case String.uncons ys of
Nothing ->
( Nothing, "" )

Just ( b, rest ) ->
( Just b, rest )

keyCode =
case ( y, z ) of
( Just a, Just b ) ->
((asciiToNumber a) * 16)
+ (asciiToNumber b)

( Just a, _ ) ->
(asciiToNumber a) * 16

( _, _ ) ->
0
in
rec zs (acc ++ (keyCode |> stringify))

True ->
acc
in
case zero of
True ->
""

False ->
rec (hex |> String.toLower) ""

References: