Interfaces and Classes in F#

Interfaces

Interfaces are declared in a similar fashion to classes but with only abstract members, for example

type ICalculator =
    abstract member Add : int -> int -> int

Classes

type Calculator() =
    member this.Add a b = a + b

Here we declared a constructor with no arguments, but we could also declare a constructor which takes arguments, such as

type Calculator(a, b) =
        member this.Add = a + b

We can also declare the constructors in the following manner

type Calculator1 =
        new () = {}
        member this.Add = a + b

type Calculator2 =
        new (a, b) = { (* do something with the values *) }
        member this.Add = a + b

Leading on from this way of declaring constructors, we can also declare multiple constructors in the following manner

type SomeClass =
    val data : string
    new () = { data = "undefined"}
    new (d) = { data = d }

Here we’ve declared a default constructor and one which takes a single argument.

or implementing the previously declared ICalculator we have

type Calculator() =
    interface ICalculator with
        member this.Add a b = a + b

To access the Add method we need to cast our value to the specific interfaces, for example

let calc = new Calculator()
(calc :> ICalculator).Add 2 3

The :> is the cast operator.

We can also implement an interface in an anonymous class, for example

let calculator() =
   {
      new ICalculator with
         member this.Add a b = a + b
   }

Inheritance

type Calculator() =
   member this.Add a b = a + b

type NewCalculator() = 
   inherit Calculator()   

Virtual functions

To declare a function as virtual we need to both declare it as abstract and create a default implementation, for example

type MyClass() = 
   abstract member myfunction : unit -> unit
   default u.myfunction() = printfn "hello"

Note: the “u.” part of the above is a self identifier. Unlike C# which has the implicit “this” identifier, we can define whatever name we wish for the self identifier

We can define a self identifier at the class level using

type MyClass() as myself = 
   abstract member myfunction : unit -> unit
   default myself.myfunction() = printfn "hello"

F# basics

Some basics of F#

#light

This directive (hash light) is used to simplify the F# syntax. Meaning the syntax is a little less verbose and removes aspects of the OCaml compatibility.

Immutable by default

By default “variables” are really just “values” as they are immutable by default so

let n = 100

initializes n to the value 100 and you cannot now alter n.

However we can mark a value as mutable and thus is can be altered, for example

let mutable n = 100
n <- n + 1

n is set to be a mutable type and n <- n + 1 is the assignment line of code, assigning n the new value of n + 1.

Assignment operator

As mentioned above, F# values are immutable, by marking them as mutable we can assign values to them. The assignment operator is not = but is <-, for example [code language="fsharp"] let mutable n = 10 // initializes n the value 10 n <- 100 // assignment of the value 100 [/code] ignore

Some functions return values which we might not actually wish to use. For example the following uses List.map to simply output the items in the array urls

let urls = ["http://www.bbc.co.uk";
             "http://www.google.co.uk";
             "http://www.amazon.co.uk"]

let f x = printfn "%s" x
List.map f urls

But the compiler will show a warning This expression should have type ‘unit’, but has type ‘unit list’. Use ‘ignore’ to discard the result of the expression, or ‘let’ to bind the result to a name for the line List.map f urls. To fix this either change this line to

let o = List.map f urls

or pipe the result to ignore as per

List.map f urls |> ignore

We can also use the following syntax

ignore(List.map f urls)

Semi-colon and commas in lists and arrays

To declare a list value in F# we use a semi-colon to denote each value of a list for example

let evens = [2;4;6;8;10;12]

This will create a val evens : int list = [2; 4; 6; 8; 10; 12]

Alternatively using a comma as per

let evens = [2,4,6,8,10,12]

This will create a val evens : (int * int * int * int) list = [(2, 4, 6, 8)]. The difference here is that with the comma we’re creating a tuple containing integers, not a list of integers.

Collection Types

List

A list is declared as

let list = [2;4;6;8;10]

Lists are ordered, immutable data of the same type.

Array

An array is declared as

let array = [|2;4;6;8;10|]

Array’s are fixed-size, zero based values of the same type.

Sequence

A sequence is declared as

let s = seq { 0 .. 10 .. 100 }

A sequence is a series of values of the same type.

Lambda expressions and anonymous functions

Anonymous functions are declared as follows

fun parameter-list -> expression

For example we might use an anonymous function in a List.map as follows

let urls = ["http://www.bbc.co.uk";
             "http://www.google.co.uk";
             "http://www.amazon.co.uk"]

List.map (fun x -> printfn "%s" x) urls

Comments

Single line comments are denoted in the same way as C# i.e.

// This is a comment

Multi-line comments are denoted using (*..*), i.e.

(*
This is a comment block
*)

Loops

The F# equivalent of a foreach

let a = [0 .. 6]
for i in a do
   printfn "%d" i

The for loop

for i = 1 to 10 do
   printfn "%d" i

for j = 10 downto 1 do
   printfn "%d" j

The while loop

let aa = [|0 .. 6|]
let mutable i = 0
  while i < (Array.length aa) do
     printfn "%d" (Array.get aa i)
     i <- i + 1

The unit type

Functions which take no arguments and/or return no values are said to take and return the type unit. This can be seen as being analogous to void in C#.

The double backtick “ in identifiers

As per Identifiers and Keywords. We can use the double backtick “ to enclose identifier that might be a language keyword, for example

let ``private`` = 1

is valid even though private is a keyword. We can also have spaces in identifiers such as

let ``add two numbers`` () =
   // function definition

Modules in F#

Modules allow us to break up source code into multiple files. There are two types of module, a top-level module and local modules.

Note: I’ve omitted any namespaces, but for completeness of this post, a name space would be added as the first line in the module files (if required) as per

namespace MyNamespace

module MyModule =
   let square x = x * x

The top-level module

The top-level module is basically a module which contains all the code for an application and it has slightly different rules regarding it’s layout compared to the local modules (see Modules (F#).

Reproducing a little from the above link we see that a top-level module does not need an = sign at the end of the module name and declarations need not be indented, for example the following is perfectly acceptable in a top-level module but not a local module

module MyModule

let hello = 
   printfn "Hello"

Local Modules

Local modules are basically re-usable files. The usual usage would be to group together related code. Unlike the top-level module, local modules require indented formatting as well as an = after the module name, so the previously define code for a top-level module would look like the following code in a local module

module MyModule =

   let hello =
      printfn "Hello"

The Program/EntryPoint module

By default the code generated by Visual Studio as the starting point for an F# applications looks like

[<EntryPoint>]
let main argv = 
    printfn "%A" argv
    0 // return an integer exit code

But implicitly this will be compiled as

module Program
[<EntryPoint>]
let main argv = 
    printfn "%A" argv
    0 // return an integer exit code

Thus conversely the module name of a top-level module can be omitted if it’s the only file in the application.

Inner Modules

Not only can a file be declared as a module but you can also have modules nested within modules, for example

module GrandParent =
   module Parent =
      module Child =
         let x = 100

Within a top-level module we can define this as

module GrandParent

module Parent =
   module Child =
      let x = 100

in other words the top level module does not need the = sign or the indenting of the Parent module.

How to use a module

So we’ve shown how to declare modules but at some point we need to use them, to achieve this we use the following

open MyModule

If we’d had a namespace we could open the namespace such as open MyNamespace. In such a case where modules were in the namespace we could prefix them on the functions, such as MyModule.square 3. Alternatively we could open the namespace and specific module(s) such as open MyNamespace.MyModule and thus have no need to prefix the functions with the module name.

[<EntryPoint>] into F#

The entry point to an F# application is declared using the attribute [<EntryPoint>]. For example, the default code when creating an F# application looks like

[<EntryPoint>]
let main argv = 
    printfn "%A" argv
    0 // return an integer exit code

This declares that the function “main” is the entry point into the application.

This is fine until you start adding modules (new source code files in F#). So if we now add a new item (F# source file) to an F# application you’ll see an error such as this

Files in libraries or multiple-file applications must begin with a namespace or module declaration, e.g. ‘namespace SomeNamespace.SubNamespace’ or ‘module SomeNamespace.SomeModule’. Only the last source file of an application may omit such a declaration.

To fix this we need to do two things. The first is that by default the new module simple gets created with the following (obviously the module name will be the same as the filename you supplied it with)

module MyModule

as the error suggests we need to create a namespace for the new module, so for example

namespace Samples.One

module Samples =
   let helloWorld =
      printfn "Hello World"

However this only solves part of the problem – the namespace issue.

The next thing we need to do is rather strange to me (maybe it’s my C++ background). But the [<EntryPoint>] file needs to be the last source code file in the project.

To make this happen, right mouse click on the Program.fs file (or whatever the name of your[<EntryPoint>] file is and using the Move Down and/or Move Up menu items, move the position of the file in the project to be the last source code file (note: it needn’t be the last actual file just the last source code file).

Note: Basically the order of the source code files is the order they’re compiled. So ordering of the files in important in F#.

MVVM Cross – Getting Started

As the primary aim of MVVM cross is to supply a cross platform MVVM framework, our primary goal must be to try to ensure that all cross platform compatible code is separated from non-cross platform. Ideally all non-UI code would be cross platform in a perfect world.

So this and any other posts on MVVM cross will assume and aim to ensure that the non-UI code is as portable as possible between platforms. The example code etc. will assume that Xamarin tools have been installed in Visual Studio, but this is not a requirement for the examples to work.

Creating the view model

  1. So to begin with we need to create a PCL (Portable Class Library). Give the project a name (i.e. I named mine Common) and then press OK, then select all the platforms you want the library to be compatible with – as I have Xamarin tools for Visual Studio installed the selected platforms include Windows, Windows 8, Windows Phone 8, Xamarin.Android and Xamarin.iOS
  2. Delete Class1.cs as we’re not going to be needing it
  3. Using NuGet, add MVVM cross to the project
  4. Now, MVVM cross uses IoC and a naming based convention approach to wiring views and view models together, so you’ll notice that by default NuGet created a ViewModels folder with a FirstViewModel.cs. Whilst you can move the location or change the namespace of the view model file, it’s name and that of the corresponding view need to map to one another. Like Caliburn Micro a XXXViewModel is mapped to an XXXView.
  5. For this sample we’ll implement the FirstViewModel implemented in Stuart Lodge’s N+1 youtube video on using MVVM cross. So edit the FirstViewModel to look like the following
    public class FirstViewModel : MvxViewModel
    {
       private string firstName;
       private string lastName;
    
       public string FirstName
       {
          get { return firstName; }
          set
          {
             firstName = value; 
             RaisePropertyChanged(() => FirstName);
             RaisePropertyChanged(() => FullName);
          }
       }
    
       public string LastName
       {
          get { return lastName; }
          set
          {
             lastName = value;
             RaisePropertyChanged(() => LastName);
             RaisePropertyChanged(() => FullName);
          }
       }
    
       public string FullName
       {
          get { return String.Format("{0} {1}", firstName, lastName); }
       }
    }
    

    Note: Our view model inherits from MvxViewModel

And that’s it for now.

So to review the above, we create a PCL library, add the MVVM cross assemblies (in this case we used NuGet), derive any view models from MvxViewModel and we’re done.

Note however that we kept the default FirstViewModel class, had we changed this name we’d also need to change the code in App.cs to reflect this change. The view model we created is basically the app view model so it’s registered in the App.cs file. But you’d get a compile time error if you didn’t make this change so that’s easy to fix.

Creating the view

Whilst it’s probably more interesting to now create an iOS or Windows Phone 8 app. I want to start with a WPF application, so here’s the process for creating a WPF app and connecting it to our view model.

  1. Create a new WPF Application project (I’m using the same solution as my PCL project created above)
  2. I’m set this project as the start StartUp project
  3. Using NuGet add MVVM cross to the references
  4. Add a reference to our PCL project
  5. Now remember that the view and view model are mapped by a naming convention, so in the Views folder you should find FirstView.xaml. Notice the view is an MvxWpfView, so similarly new views should also be derived from this class.
  6. Again, as per Stuart Lodge’s N+1 video we’ll simply add the following to the XAML for the FirstView.xaml
    <TextBox Text="{Binding FirstName, Mode=TwoWay}"/>
    <TextBox Text="{Binding LastName, Mode=TwoWay}"/>
    <TextBlock Text="{Binding FullName, Mode=OneWay}"/>
    
  7. Finally and before we can run this code. I named my PCL assembly Common and thus we need to change the Setup.cs file to reflect this. the method CreateApp needs to look like this

    protected override IMvxApplication CreateApp()
    {
       // uses the App object in our PCL assembly
       return new Common.App();
    }
    

Now this should run – no need to assign any views to the MainWindow, MVVM cross will handle this for you based upon your App class in the PCL assembly.

Indexing your MongoDB data

By default MongoDB creates an index on the _id (ObjectId) field, but we can easily add indexes to other fields.

Using the JavaScript shell

In the JavaScript shell simply call ensureIndexUsing the 10gen drivers in C#

In C# using the 10gen drivers we can create an index using the following

collection.EnsureIndex(new IndexKeysBuilder().Ascending("artist"));

where collection is

MongoCollection<CD> collection = db.GetCollection<CD>("cds");

To remove an index we can simply use

collection.DropIndex(new IndexKeysBuilder().Ascending("Artist"));

Handling case-sensitive mapping from MongoDB to a POCO

So the convention appears to be to use camel case for column/field names within MongoDB. For example if we create an entry such as db.cds.Update({artist:”Alice Cooper”}).

In C# the convention is for properties, for example, to be written in Pascal case. So we’d have something like

public class CD
{
   public ObjectId Id { get; set; }
   public string Artist { get; set; }
   public string Title { get; set; }
   public string Category { get; set; }
}

So obviously MongoDB has a field name artist and we need to map it to the property name “Artist”.

To handle this we can use the BsonElement in the MongoDB.Bson.Serialization.Attributes namespace, as per

public class CD
{
   public ObjectId Id { get; set; }
   [BsonElement("artist")]
   public string Artist { get; set; }
   [BsonElement("title")]
   public string Title { get; set; }
   [BsonElement("category")]
   public string Category { get; set; }
}

or we can set up the mappings using the following

BsonClassMap.RegisterClassMap<CD>(cm =>
{
   cm.AutoMap();
   cm.GetMemberMap(c => c.Artist).SetElementName("artist");
   cm.GetMemberMap(c => c.Title).SetElementName("title");
   cm.GetMemberMap(c => c.Category).SetElementName("category");
});

Note: we do not need to setup the Id field to any mapping as this appears to be mapped based upon it’s type.

A class map may only be registered once, we can use BsonClassMap.IsClassMapRegistered if need be to ensure this.

More information can be found at Serialize Documents with the CSharp Driver

Starting out with MongoDB

This is a post on some of the basics of using MongoDB (on Windows).

mongod.exe

So to run the mongo server we use mongod.exe, if all goes well the server will start up and state it’s waiting for connections.

mongo.exe

The JavaScript shell used as the client admin application for the mongo server is named mongo.exe.

Shell Commands

  1. use <database> is used to switch the shell to using the named <database>. If this command is not used, be default the test database will be used.
  2. show dbs can be used to get a list of all the databases stored in the instance of MongoDB.
  3. show collections lists the available collections within the selected database. This is analogous to listing the tables in an SQL database.
  4. show users lists the users added to the database. To add a user via the JavaScript Shell we can use the following
    db.addUser({user: "UserName", pwd: "Password", roles: ["readWrite", "dbAdmin"]})
    

    Beware, as the roles are not validated against any schema or role list, so you can assign roles names which are not recognised as specific mongo roles, i.e. I made a typo for dbAdmin and it’s accepted as a role.

  5. db is the database object, so we can execute commands such as db.stats()
  6. db.myobjects let’s assume we created a database and added some objects into a collection named myobjects. Because we’re using a JavaScript shell we can access the myobjects collection off of the db object. So for example we can now using db.myobjects.count() to get a count of the number of “rows” in the collection. Equally we can use commands such as db.myobjects.find() to list the rows in the collection.

Example workflow

This is a simple example of using mongo.exe to create a database and some data, then querying the database.

For this example we’ll create a CD database which will be used to contain information on all the CD’s we own.

  1. If it’s not already running, run mongod.exe
  2. In a separate command prompt, run mongo.exe
  3. We’ll create the database by typing use CDDatabase, remember it will not be fully created until some data is added to it
  4. We can check which database we’re currently viewing by typing db. This will show us we’re in the CDDatabase, but if you now type show dbs you’ll notice the database still doesn’t actually exist in the list of available databases
  5. We can now create our first entry in the database. Notice, unlike an SQL database we do not create tables etc. So to create an entry we can type the following
    a = {artist:"Alice Cooper", title:"Billion Dollar Babies", category:"Rock"}
    db.cds.insert(a)
    

    Note: we don’t need to create a variable as we’ve done here, we can just replace ‘a’ in the insert method with the right hand side of the = operator as per

    db.cds.insert({artist:"Alice Cooper", title:"Billion Dollar Babies", category:"Rock"})
    

    So we should have now successfully added an entry into the “cds” collection. Notice again we do not need to define the “cds” collection first, it’s dynamically created when we start using it.

    We can use the command show collections to display a list of the collections that make up the datavase.

    Feel free to add more data if you wish.

  6. Let’s now see what’s in the collection dbs. To do this simply type db.cds.find(). You should now see all the entries within the “cds” collection that you created. Notice that a variable _id of type ObjectId has been added to our data.

    To find a single entry, in this example we’ll find the artist by name we simply use db.cds.find({artist:”Alice Cooper”})

  7. So as part of the standard CRUD operations on data, we’ve seen how to Create and Read data, now let’s look at updating data. Run the following command
    db.cds.insert({artist:"Iron Maiden", title:"Blood Brothers"})
    

    Now I’m left off the category here, so we now need to update this entry. We use the collection’s update method, thus

    db.cds.update({artist:"Iron Maiden"}, {$set:{category:"Heavy Metal"}})
    

    The first argument in the update method {artist:”Iron Maiden”} is the query string, in other words update where artist is “Iron Maiden”. The second argument is the update action, which simply tells update to set the category to “Heavy Metal”.

    If we run this command we’ll see the category added, but this command works only on the first item found, so if there were multiple “Iron Maiden” entries missing the category this would be a bit of a problem. However we can apply a third argument to update to solve this.

    db.cds.update({category:"Rock"}, {$set:{category:"Heavy Rock"}},{multi:true})
    

    The addition of {multi:true} will allow the update to be applied to all matching entries.

  8. Now to the final CRUD operation – Delete. This is simply a case of using the collection’s remove method. For example
    db.cds.remove({artist:"Alice Cooper"})
    

    Be careful not to forget the query part of this method call, the {artist:”Alice Cooper”} as using db.cds.remove() will remove all entries from the collection.

Creating a simple database in MongoDB with C#

This is quick post on getting up and running with MongoDB using the “Official MongoDB C# driver” and both creating a database and adding some data to it.

  1. Using Nuget, add the “Official MongoDB C# driver” from 10gen to your project
  2. Add the following using clauses
    using MongoDB.Bson;
    using MongoDB.Driver;
    
  3. Create a POCO object to represent the data you want to persist. The key thing to remember is to add a property of type ObjectId without this we’ll get and exception stating “No IdGenerator found”.

    So an example POCO might look like this

    public class Person
    {
       public ObjectId Id { get; set; }
       public string FirstName { get; set; }
       public string LastName { get; set; }
       public int Age { get; set; }
    }
    
  4. Now we need to connect to the server and create/use a database.

    MongoClient client = new MongoClient();
    MongoServer server = client.GetServer();
    MongoDatabase db = server.GetDatabase("MyDatabase");
    

    Obviously the first two lines create a mongo client and then gets access to the server. The line server.GetDatabase(“MyDatabase”) will get the database (if it exists) but also create a database if it doesn’t exist.

    Note: if you are creating a database using GetDatabase it will not exist until you actually store data in it.

  5. Next we’re going to assume we want to store a collection of employees (a collection of Person objects). So we want to get the collection of “employees”. Like the creating of the database, if no employees currently exist we still get a collection object which we can then save data to.

    MongoCollection<Person> collection = db.GetCollection<Person>("employees");
    
  6. Let’s now create a Person object ready for adding to the collection and ultimately to the database.

    Create the following

    Person p = new Person
    {
       Id = ObjectId.GenerateNewId(),
       FirstName = "Bob",
       LastName = "Baker",
       Age = 36
    }
    

    Notice that we generate the Id using ObjectId.GenerateNewId().

  7. Our next step is to save the new Person to the collection and this will add the data to the collection and thus the database, thus we can then query for this data afterwards using the JavaScript shell.

    collection.Save(p);
    

Setting up my Raspberry Pi

As this is the third Raspberry Pi I’ve had to set up, and again I’ve forgotten the steps. Here’s a post of what I need.

Steps…

  1. Ensure the OS is upto date
  2. Setup a WiFi USB device (I’m using the EDIMAX USB Adapter)
  3. Setup a static IP address
  4. Install mono
  5. Install Git tools
  6. Setup VNC

Fire up the Pi and login…

Ensure the OS is upto date

sudo apt-get update

This will update all packages.

You can also run

sudo apt-get upgrade

to upgrade the Linux kernel

Setup a WiFi USB device (I’m using the EDIMAX USB Adapter)

The EDIMAX EW-7811Un is on the list of WiFi USB adapters that’s verified for use on a Raspberry Pi and it’s the one I’ve used previously so I know it works :)

Note: An excellent and fuller guide is available at Raspberry Pi – Installing the Edimax EW-7811Un USB WiFi Adapter (WiFiPi)

I’ll just reproduce the steps I used here

  1. So obviously we need to start by plugging the USB adapter into the Raspberry Pi
  2. Next run
    iwconfig
    

    This will tell us whether the adapter is ready to use as it should automatically have been recognized. You should see wlan0 plus other information output. Check the link above for more tests you can do to ensure everything is detected and read.

  3. Now we want to ensure that the adapter is configured, so type
    sudo nano /etc/network/interfaces
    

    or use your preferred text editor in place of nano.

    Make sure the file contains the following (and they’re uncommented)

    allow-hotplug wlan0
    iface wlan0 inet manual
    wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
    iface default inet dhcp
    
  4. Now we need to create/amend the configuration file for connecting to the network, so type
    sudo nano /etc/wpa_supplicant/wpa_supplicant.conf
    

    We need to add the various entries for connecting to the network here, for example

    network={
       ssid="The Router SSID"
       psk="The Router Password"
       proto=WPA
       key_mgmt=WPA-PSK
       pairwise=TKIP
       auth-alg=OPEN
    }
    

    Obviously replace the ssid and psk with your router’s ssid and the password you use to connect to it.

  5. Type the following, to restart the network interface with the new configuration data

    sudo ifup wlan0
    

Setup a static IP address

Open /etc/network/interfaces again, for example using

sudo nano /etc/network/interfaces

We now want to change the configuration from using dhcp supplied address to using a static ip address. So alter the line

iface default inet dhcp

from dhcp to static and add the following

address 192.168.1.100
gateway 192.168.1.1
netmask 255.255.255.0

Obviously replace the address, gateway and netmask with your specific network settings. You may also wish to alter the eth0 adapter to mirror the wlan0 adapter with the same address etc.

Install mono

Finally time to install something. This is the easy part. To install mono just enter the following

sudo apt-get install mono-complete

Install Git tools

Time to install GIT.

sudo apt-get install git

Setup VNC

Install VNCServer using

sudo apt-get install tightvncserver

Now run tightvnsserver and note the number supplied for the desktop for connection from the client machine.

Raspberry Pi A+

The Raspberry Pi A+ has a single USB port (excluding the USB power socket) and no Ethernet port, which is a bit of a pain if trying to setup WiFi and having problems getting the configuration right (especially as I don’t have a powered USB hub to help me out).

Anyway after a lot of hassle here’s the configuration for the Raspberry Pi A+ running Wheezy Raspbian 7. The USB WiFi device I’m using is a WiPi dongle.

Let’s begin with the /etc/network/interfaces file, mine looks like this

auto lo
iface lo inet loopback

auto wlan0
allow-hotplug wlan0
iface wlan0 inet manual
wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
iface default inet static

address 192.168.1.2
gateway 192.168.1.
netmask 255.255.255.0

obviously the above is setup with a static address, if you want to use a dynamic address change the static to dhcp and remove the address gateway and netmask (to tidy the config up).

Next we need to amend the /etc/wpa_supplicant/wpa_supplicant.conf file, mine looks like this

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
ssid="The Router SSID"
psk="The Router Password"
proto=RSN
key_mgmt=WPA-PSK
pairwise=CCMP TKIP
group=CCMP TKIP
}

The above configures for WPA2 security (use WPA for WPA1).