Category Archives: F#

List basics in F#

In a previous post I touched on F# lists, now let’s look a little further into the F# lists.

Note: Also check out Lists (F#) for a far more comprehensive view of F# lists

The MSDN documentation states that F# lists are implemented as singly linked lists.

Creating Lists

First off we can create a list using square brackets and semi colon delimiters, for example

let list = ["One"; "Two"; "Three"]

This creates a string list using type inference, i.e.

val list : string list = [“One”; “Two”; “Three”]

Had we wanted we could also create a list with a type hint mirroring this line (note the string list type hint)

let list : string list = ["One"; "Two"; "Three"]

We can also define this list without the semi-colon delimiter, instead using newlines as per

let list = [
   "One"
   "Two"
   "Three"]

We can declare an empty list as follows

let list = []

We can also declare lists using the range operator, for example

let list = ['a' .. 'z']

Whilst we can define a list of data as above, we can also generate the list in the following way

let list = [for i in 'A' .. 'Z' -> i]

Operators

The double colon :: operator takes a left hand argument as a single item and the right hand side as a list and creates a new list which is made up of the left hand argument and then right hand list appended to it. So, for example

let original = [1; 2; 3]
let list = 0 :: original

will result in list being [0; 1; 2; 3]

We can also concatenate lists using the @ operator, for example

let right = [1; 2; 3]
let left = [3; 2; 1]

let combined = left @ right

This results in a new list which looks like [3; 2; 1; 1; 2; 3]

Operator overloading in F#

F# allows us to override existing operators and even create our own. There are two types of operators, prefix and infix.

Prefix operators are those which take one operand. Infix operators take two arguments.Unlike C# both operands in an infix operator must be of the same type.

Along with overloading existing operators we can create custom operators using a single or multiple characters from the following !$%&+-,/<=>?@^|~

For example, let’s define a global operator !^ which will calculate the square root of a floating point number

let inline (!^) (a: float) = Math.Sqrt(a)

and in usage

let sqrt = !^ 36.0
printfn "Sqrt %f" sqrt

An infix operator is declared taking two arguments, so here’s an example of a value to the power n, which we’ll use the operator ++ which can be defined as

let inline (++) (x: float) (y: float) = Math.Pow(x, y)

and in usage

let a = 10.0 ++ 2.0

When declaring operators on a type (as opposed to globally) we have the following

type MyClass2(x : int) =
    member this.value = x
    static member (~+) (m : MyClass2) = 
        MyClass2(m.value + 1)
    static member (+) (m : MyClass2, v : int) = 
        MyClass2(m.value + v)

// usage 

let m = new MyClass2(1)
let n = m + 5

Unit testing in F#

There are several libraries for writing unit tests in F#. FsUnit allows us to reuse xUnit, NUnit or MbUnit.

So using FsUnit with xUnit do the following

  1. Add a new Library project
  2. Using NuGet, add a reference to FsUnit.Xunit

Now we can write our tests using the following

open FsUnit.Xunit
open Xunit

module Tests =

   [<Fact>]
   let ``add two numbers`` () =
      let m = new Mathematics()
      m.add 1 3 |> should equal 4

using backtick notation for identifers is useful for helping us write human readable test names.

Pattern matching in F#

Pattern matching allows us to use a more powerful form of if..then..else or switch/select case type statements.

We declare a pattern matching implementation as follows

let option o =
   match o with
   | 1 -> "item 1"
   | 2 -> "item 2"
   | _ -> "unkown"

// usage
let choice = option 2

The _ is used as a wildcard character, i.e. anything not matching the patterns above..

We can also add matching along the lines of

let option o =
   match o with
   | o when o <= 0 -> failwith "value must be greater than 0"
   // other patterns

You can also match to more than one pattern as per

let option o =
   match o with
   | 1 | 2 -> "one or two"
   // other patterns

We can also pattern match on tuples for example

let options tuple =
match tuple with
   | "one", 1 -> "got one"
   | "two", 2 -> "got two"
   | _, _ -> "unknown"

// usage
let k = options ("one", 1)
printfn "%s" <| k 

Better still we can ignore part of a tuple

 let options tuple =  match tuple with    | "one", _ -> "got one"
   | _, 2 -> "got two"
   | _, _ -> "unknown"

// usage
let k = options ("?", 2)
printfn "%s" <| k 

or we could use the following to denote tuples

 let options (a, b) =     match (a, b) with    | "one", _ -> "got one"
   | _, 2 -> "got two"
   | _, _ -> "unknown"

let k = options ("?", 2)
printfn "%s" <| k

Type pattern matching

We can also use the pattern matching to match against the type of the value passed to it, for example

<![CDATA[
let value = 3.12f

let y =
   match box value with
   | :? System.Int32 -> "integer"
   | :? System.Single -> "float"
   | :? System.String -> "string"
   | _ -> "undefined"

printfn "%s" <| y
]]>

In the above we need to use box, alternatively we can use the following

let y (o: obj) =
   match o with
   | :? System.Int32 -> "integer"
   | :? System.Single -> "float"
   | :? System.String -> "string"
   | _ -> "undefined"

printfn "%s" <| string y

Note: Here, instead of creating a let statement to get the result from the match I’m supplying it directly to the printfn function. Interestingly whilst the return is a string and the printfn I set to output a string, at this point it’s a generic string and we need to cast it directly to a string (non-generic)

Type Extensions in F#

There are two types of type extensions. The first would be seen more like a partial class in C# and the second are extension methods (in C# language).

Intrinsic Type Extension

So the first type of type extension is an intrinsic extension which appears “in the same namespace or module, in the same source file and in the same assembly as the type being extended” (as take from Type Extensions (F#).

Basically an intrinsic type extension can be compared to a C# partial class. It’s a way of breaking down the implementation of a class into multiple files/locations for maintainability etc.

An example of this syntax is

namespace MyNamespace

module MyType =

    type HelloWorldClass = 
        new() = {}
        member this.Hello() = printfn "hello"
        member this.World() = printfn "world"

    type HelloWorldClass with 
        member this.Exclamation = printfn"!"

The second type declaration using the with keyword to declare the extensions to the type.

Obviously when we create an instance of HelloWorldClass the methods Hello, World and Exclamation are all visible to the calling code as if they’d been writing in the one type declaration.

Options Type Extensions

Similar to the previous type extension in syntax and like C# extension methods will only be visible when loaded. For example if we want to extend a String class to add a method to capitalize the first letter of a string and have the rest lower case we might declare the following

type System.String with
   member this.CapitalizeFirstLetter =
      this.Substring(0, 1).ToUpper() + this.Substring(1).ToLower()

Notice the use of the self identifier used throughout the declaration. In usage this would now appear as an extension to the System.String class and we could use it as follows

let s = "hello"
printfn "%s" <| s.CapitalizeFirstLetter

Using F# from C#

Let’s take a simple example – we have a library in F# which has functions that we want to use in C#. In this case we’ve got a Fibonacci function.

  1. Create a C# console application (for this demo)
  2. Add a new F# Library project (I named mine FLib)
  3. Add the following code to the library
    namespace FLib
    
    module Mathematics =
    
        let rec fib n = if n < 2 then 1 else fib (n - 1) + fib (n - 2)
    

    Note: you must include the module if you want to declare values/functions in a namespace

  4. Now in the C# application add the using clause

    using FLib;
    
  5. And finally we use the function as per the following
    int result = Mathematics.fib(5);
    

    The module appears list a static class with static methods.

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#.