bridging the gap: functional csharp

I would love to do more (or any) professional Haskell and I am really happy that I can do F# in my day to day work but the sad fact is: most of you probably may not (or don’t want to) use F# in your day-job and do C#.

Now that does not mean that you cannot program in a functional fashion – not at all. It only means that you might have to consider carefully if the different paradigm (and maybe the additional fight with C#s inferior type-inference and lacking syntax caps) will hinder you too much.

With this I want to start a small series where I give some examples of how the same small problem can be solved in a functional way in my favorite languages.

I hope some of you will sent me some proposals for future topics.

If not I will tease you with my usual non-real-life examples.

today’s problem: the Caesar cipher

As a first and easy example I want to show how a implementation of the infamous Caesar cipher could look like in Haskell, F# and finally C#.

For those of you who don’t know this algorithm: it’s a very easy encoding scheme (that you should never use in more than toy examples and games for kids) that Caesar used to hide messages from enemies.

You basically shift your alphabet by a constant (the key) to switch from plaintext to ciphertext:

Caesars cipher

The decoding is the same only that you shift in the other direction.

In programming you typically shift using addition modulo the max. representable number/character to get a bijection (the inverse here is the same function with the negative key).


Just pick the once you (can) understand and ignore the rest – I’m sure you get it 😉

Haskell version

A (hopefully readable) example implementation:

import Data.Char (ord, chr)

caesar :: Int -> String -> String
caesar key = map encode
  where encode  = chr . shift . ord
        shift c = (c + key) `mod` max'
        max'    = ord maxBound

here is a test-run

λ> let cipher = caesar 3 "Hello"
λ> cipher
λ> caesar (-3) cipher

F# version

In F# we usually don’t use point-free-style as much and prefer piping so a idiomatic version might look like this:

module Caesar =
    let private makeString (cs : char seq) =
        System.String (Seq.toArray cs)

    let private shift key (text : string) =
        let max = int System.Char.MaxValue
        |> int
        |> (fun n -> (n + key) % max)
        |> char
        |> makeString

    let encode key = shift key
    let decode key = shift -key

Please not that right now we cannot easily use constructors as functions and with |> so I introduced makeString (something you will see again shortly) – aside from this it’s more or less a typical translation from Haskell into F#.


  > let enc = "Hello" |> Caesar.encode 3;;
  val enc : System.String = "Khoor"

  > let dec = enc |> Caesar.decode 3;;
  val dec : System.String = "Hello"

C# version

You can now easily translate the F# version into C# by using extension-methods and LINQ (focus on ShiftCipher):

    public static class Caesar
        static string MakeString(this IEnumerable<Char> characters)
            return new string(characters.ToArray());

        static string ShiftCipher(this string text, int key)
            const int max = (int)Char.MaxValue;
                    .Select(c => (int)c)
                    .Select(n => (n + key) % max)
                    .Select(n => (char)n)

        public static string Encode(this string text, int key)
            return text.ShiftCipher(key);

        public static string Decode(this string text, int key)
            return text.ShiftCipher(-key);

and aside from having a bit more boilerplate and {/}s the piping with extension methods seem to work quite nicely (don’t you think?).

Here is the usual test-run:

var enc = "Hello".Encode(3); // = Khoor
var dec = enc.Decode(3);     // = Hello

Now of course this is a static class and stuff and your OOP heart might want you to transform this into some singleton-pattern or other OO-shit but please don’t 😉

Is it really that hard to pass the key parameter around? I don’t think so.


Leave a comment 😉


Mathias Brandewinder suggested this Test Run article via twitter as a further example – I have to look at it more carefully (it’s been quite some time I did something like this) but I like the idea – maybe we can compare after – it might take some time though, but easter vacation is comming (even if it looks more like winter at the moment)