F# is a programming language that allows you to write simple code to solve complex problems.
The quote comes from Don Syme.
With programming language, Don means that F# is not a new platform, but just another language on the CLR. This means that the libraries that already works for C# and VB.NET are likely to also work well with F#.
One strength with F# is to express as much intent as possible with little code. The theory is that quantity of code cause bugs and if we could limit the amount code we fwouusers limit the amoutnt of bugs. Reports from users has also told stories about exceptionally small amount of bugs in code produced in F#. This might be a hard statement to prove since F# draws the attention of developers of a different kind.
Don Syme says that F# is not a language meant to solve all problems, but specific problems of a complex nature. F# has never meant to replace C# or VB and is not suitable for tasks that depends on changing a mutable state. The first thing that comes to mind is Workflows and state machines.
Since every good thing comes in trees we should specify the big threes for functional programming.
We will look at what a function is in F# and how treating everything as a function changes the way you code.
If you define a variable in F# it is immutable by default which means that its value will never change. This changes the way you loop and aggregate things in F# compared to an imperative language like C#.
You will find the F# interactive window in the View/Other Window menu option. This is where you can evaluate your expressions as you code. Simply copy the code to the interactive and add double semicolon ';;' to evaluate, or use one of the shortcut commands in Visual Studio. Mine is, mark the code to evaluate and press Alt + '
let area w h = w * hResult:
val area : int -> int -> int
let half x = x / 2Result:
val half : int -> int
let triangleArea w h = half (area w h)Result:
val triangleArea : int -> int -> int
let myTriangle = triangleArea 2 4Result:
val myTriangle : int = 4
A function is defined with the keyword let. First argument is the name of the function and the rest are arguments to that function. After the "=" (equals sign) comes the function body. In F# we don't make a distinction between variables and functions with no arguments. These are the same. If the expression can be evaluated it will.
Argument types are inferred at compile time. Sometimes the compiler can't inferr the types and we'll have to specify them explicity.
This imperative language uses the side effect of the for loop to change the mutable state of the result variable
namespace LiteMedia.CSharpLecture
{
public class Example1
{
const int Max = 100000;
public void Aggregate()
{
var result = 0;
for (int i = 1; i < Max; i++)
result += i;
System.Console.WriteLine(result);
}
}
}
If the world can't change it won't have side effects. Since the world can't change we continue to create new and better versions of the world.
Imperative programming languages depends on changing states of the program. This is why you aggregate by adding numbers to a result variable.
In a functional programming language where variables are immutable, state won't change.
let sum max = let result = 0 for i = 0 to max do result <- result + i result sum 100000Result:
error FS0027: This value is not mutableYou can't change the state of an immutable variable. This means that
let rec sum max = if max = 0 then 0 else max + sum (max - 1)
sum 3 = 3 + (sum 2)
sum 2 = 2 + (sum 1)
sum 1 = 1 + (sum 0)
sum 0 = 0
3 + 2 + 1 + 0 = 6
Since we can't change the value we will have to create a new value, and easiest way of doing that is calling the method again with different arguments. This is called recursion.
let rec sum max = match max with | 0 -> 0 | _ -> max + sum (max - 1)
let rec sum = function | 0 -> 0 | n -> n + sum (n - 1)
Recursion is not done in F# with if statements, but with matching patterns. This works pretty much like a switch statement on steroids.
let sum max = [1..max] |> List.fold (+) 0
var result = Enumerable.Range(1, Max).Aggregate((acc, x) => acc + x);
let sum max = seq { for i in 1..max do yield i } |> Seq.fold (+) 0
Recursing to sum up all the digits from 1-100000 is quite unnessesary. This is how you would do it by using a list, and F# built in Fold.
You can accomplish the same thing with Linq.Aggregate.
Since Linq.Aggregate yields numbers as we request them, this is a more effective solution. The F# code has to first create the list and then sum it up. We can mend this by also yielding numbers.
Even though, the F# solution is 66 characters and the C# solution is 72.
let pair = 7, 4 let a, b = pair
let triplet = 7, 4, 2 let _, _, c = triplet
let b, a = a, b
Pattern matching is essential in F#. You use it to reduce conditional code and to simplify things. In this example i create a tuple and then extract the tuple values into a and b by matching the tuple to values.
In next example I create a triplet, but extract only the third value. The underscore means that I don't care about the first two.
Last I take a and b, and swap them into d and e.
let compare n1 n2 = match n1, n2 with | a, b when a < b -> -1 | a, b when a > b -> 1 | _ -> 0
type OddEven = | Odd | Even let isOddEven n = match n % 2 = 0 with | true -> Even | false -> Odd
Pattern matching is mostly used with the match..with construct that works like an overpowered switch case. In the first example I match two values, n1 and n2. Return -1 if n1 is less than n2, and 1 if n1 is larger than n2. Otherwise, if they are equal, return 0.
This is a standard .NET comparison.
isOddEven matches the result of the function call with true/false. When n%2=0 then return Even, else return Odd.
let rec square (o : Object) = match o with | :? int as x -> x * x | :? float as x -> int (x * x) | :? string as x -> square (Int32.Parse x) | _ -> failwith "object type not supported"
Will square an int, float or a string
You can match .NET types. Recieve an input as untyped object, and do different things with it depending on what type it has.
(+)Result:
val it : (int -> int -> int)
(*) 6 7Result:
val it : int = 42
let (++) a b = (a + b) * 2 5 ++ 7Result:
val ( ++ ) : int -> int -> int
val it : int = 24
Operators are functions too. Just evaluating the + operator will tell us that it is a function that takes two integers and returns an integer. We can use it as a function with prefix notation as well as the more ordinary infix notation.
Creating our own custom operators is trivial, just like defining any function and can be used with both prefix and infix notation.
val it : ('a -> ('a -> 'b) -> 'b)
25. |> sqrtResult:
val it : float = 5.0
[1.; 9.; 25.; 625.] |> List.map sqrtResult:
val it : float list = [1.0; 3.0; 5.0; 25.0]
var result = new[] { 1.0, 9.0, 25.0, 625.0 }
.Select(Math.Sqrt);
The pipe (|>) operator takes an argument and a function, and uses that argument as the last argument to the function. The function must take an argument of that type as its last argument.
let addFive = (+) 5 addFive 10Result:
val addFive : (int -> int)
val it : int = 15
let equalsSpagetti = (=) "spagetti" equalsSpagetti "fusilli"Result:
val equalsSpagetti : (string -> bool)
val it : bool = false
When we call a function with less arguments we create a new function with the missing parameters as arguments.
Just like lambdas in C# we have anonymous functions in F#.
(fun x -> x * x) 7Result:
val it : int = 49
Func<int, int> square = (int x) => x * x; square(7);
Just like in C# we have anonymous functions in F#. We use these as arguments to other functions.
For every number from 1 to 10, filter out those that are x % 2 = 0, even.
[1; 2; 3] |> List.map (fun x -> x * 2)
new[] { 1, 2, 3 }.Select(x => x * 2);
[1; 2; 3] |> List.filter (fun x -> x % 2 <> 0)
new[] { 1, 2, 3}.Where(x => x % 2 != 0)
[1; 2; 3] |> List.fold (+) 0
new[] { 1, 2, 3}.Aggregate((acc, x) => acc + x)
Higher order functions are functions that mostly operate on lists and take other functions that define what should be done. Most common higher order functions are Map, Filter and Fold.
val it : (('a -> 'b) -> ('b -> 'c) -> 'a -> 'c)
let shortest l = l |> List.minBy (fun (s : string) -> s.Length)Result:
val shortest : string list -> string
let length (s : string) = s.LengthResult:
val length : string -> int
let lengthOfShortestString = shortest >> lengthResult:
val lengthOfShortestString : (string list -> int)
We can add functions together in F#, very much like calling a function with the result from another function. We do this with the operator << or >>. That means, take the result of this function and feed it to the next function. This can be very useful for simplify things.
Have you ever seen the null reference exception YSOD? Then you will be glad to know that no function in F# may return null.
let rec findPrime l = let isPrime n = [2..(n/2)] |> List.exists (fun x -> n % x = 0) |> not match l with | [] -> None | head :: tail when head |> isPrime -> Some(head) | head :: tail -> findPrime tail
let hasPrime l = match findPrime l with | None -> false | Some(x) -> true [4; 6; 8; 9; 11] |> hasPrimeResult:
val it : bool = true
Instead of returning null we use the new Some(x)/None functionality. This lets us match on the return value. In this example we have a function that will return first prime number in the list, or None.
We can create a hasPrime function that will check if we get Some(x) that is prime or if we get None.
val findPrime : int list -> int option
match findPrime l with | None -> false | Some(x) -> true
type Name = string type FullName = Name * Name
let printFullName name =
let firstName, surname = name
printfn "My name is: %s %s" firstName surname |> ignore
printFullName ("Mikael","Lundin")
Creating your own types makes it easier to extend your system in the future.
type Book = { Title : string; Author : string }
let book = { Title = "The Treasure Island";
Author = "Robert Lewis Stevenson" }
book.Title <- "Treasure Island"Result:
error FS0005: This field is not mutable
If you need to define more complex data structures you can define a record type. But you'll have to remember that this type is immutable as everything else. You can't change its values once it has been set.
type Point = { x : int; y : int }
let graph fn width height =
// Is point y between y1 and y2
// int -> int -> Point -> bool
let yBetween y1 y2 point = point.y > y1 && point.y < y2
// For all x, -100 to 100
[-(width / 2)..(width / 2)]
|> List.map (fun x -> { x = x; y = fn x})
|> List.filter (yBetween -(height / 2) (height / 2))
In this example we would like to spot a graph on a panel.
It's nice to notice that the compiler will asume that we create a Point type at line 10, and we use the partial method yBetween to filter out points at line 11.
When I see such code, I find it amusing to think that F# is a statically typed language and yet, we don't specify types anywhere but in the type definition. The compiler will try to find out the types as we go and will tell us where it fails.
graph (fun x -> 2 * x + pown x 3) 200 200
Result: val it : Point list = [{x = -4; y = -72;}; {x = -3; y = -33;}; {x = -2; y = -12;}; {x = -1; y = -3;}; {x = 0; y = 0;}; {x = 1; y = 3;}; {x = 2; y = 12;}; {x = 3; y = 33;}; {x = 4; y = 72;}]
The panel is 200x200 and the graph we would like to draw is y = 2x + x^3. For this purpose we use create a series of point types from x = -100 to x = 100 with the distinction that y also has to be within -100 < y < 100.
type Queue() = let mutable queue = [] member this.Empty = queue = [] member this.Push x = queue <- queue @ [x] member this.Pop = match queue with | [] -> None | head :: tail -> queue <- tail Some(head)
You create a class very much like a record. When you want to specify member methods you use the keyword member instead of let. I use this to identify the current instance of the class.
Since object oriented programming is very much about changing states of objects, you can create mutable fields within the class. You specify the mutable keyword after let to tell F# that the field is mutable.
type Queue =
class
new : unit -> Queue
member Push : x:obj -> unit
member Empty : bool
member Pop : obj option
end
let queue = new Queue()Result:
val queue : Queue
[1; 2; 3] |> List.iter queue.PushResult:
val it : unit = ()
let rec dequeue (q : Queue) = match q.Empty with | true -> [] | false -> q.Pop.Value :: dequeue q dequeue queueResult:
val dequeue : Queue -> obj list
val it : obj list = [1; 2; 3]
You create a new instance the same way you do in C# with the new keyword.
We can write a function that will dequeue the whole queue into a list.
let comparer =
{ new IComparer<string> with
member self.Compare(s1, s2) =
s1.Length.CompareTo(s2.Length)
}
let names = new List<string>([|"Mikael"; "Hjalmar"; "Jenny"|]) names.Sort(comparer)Result:
val it : List<string> = seq ["Jenny"; "Mikael"; "Hjalmar"]
[<Measure>] type m [<Measure>] type s let distance = 100.0<m> let worldRecord = 9.58<s> let speed = distance / worldRecordResult:
val speed : float<m/s> = 10.43841336
let km = 1000.0<m> let h = 3600.0<s> let speedInKmPerHour = speed / (km/h)Result:
val it : float = 37.5782881
What is an int? When I went to school we were forced to answer every math
question with the unit of the answer.
- If you take two apples and add three apples, how many apples have you got?
- Five!
- Five, what?
- Five apples.
With this in mind, an int is not just an int. We usually try to tell in the variable name, what the int symbolizes but that is not very type safe. Welcome to a world of units of measure.
// Identity monad
type Identity<'a> =
| Identity of 'a
type IdentityBuilder<'a>(v : 'a) =
let value = v
member self.Bind ((Identity v), f) = f(v)
member self.Return v = Identity v
let identity = new IdentityBuilder<int>(0)
let answerToEverything =
identity { return System.Int32.Parse("42") }
This is an Identity Monad defined in F#. If you don't know what a monad is, you don't have to, because in F# this is abstracted into computational expressions. When a monad is defined it can be used as a computational expression as you see on line 13.
This leads us on to...
open System.Net
open Microsoft.FSharp.Control.WebExtensions
let webGet (name, url) =
async {
let uri = new System.Uri(url)
let webClient = new WebClient()
let! html = webClient.AsyncDownloadString(uri)
return name, html.Length
}
let addresses = [ "Valtech", "http://www.valtech.se";
"LiteMedia", "http://litemedia.se" ]
let contentLengths =
addresses
|> Seq.map webGet
|> Async.Parallel
|> Async.RunSynchronously
Async in F# is a monad. That means that you write asynchronous tasks within a computational expression and bind the async monad to a async task.
webGet is a function with the signature 'a * string -> Async<'a * int> and this
enable us to run several instances of this function in parallel. There are several helper functions in
F# like AsyncDownloadString that will make it easier for us to write these async tasks.
The example will get content lengths of addresses of a list, in parallel.
type Agent<'a> = MailboxProcessor<'a>
// Asyncronous agent
let agent =
Agent.Start(fun messages ->
async { while true do
let! message = messages.Receive()
printfn "New message: %s" message } )
agent.Post("Hello World")
Asynchronous agents are useful when you need to create a fast and lightweight way to handle message processing. This is very much done like async events, when something happens it should react in a specific way.
open Xunit // SUT let add a1 a2 = a1 + a2 [<Fact>] let ShouldAddTwoNumbersTogether() = let result = add 8 4 Assert.Equal(12, result)
Most exciting part of unit testing with F# is the complete lack of ceremony.
All you need is an open Xunit and you're all set writing tests.
Notice the end parathesis of the let function. This is needed because without
it F# will give a function with the definition unit where as Xunit
will look for tests with the definition unit -> unit. The paranthesis
forces this function signature.
public class LoginController
{
private readonly IRepository<User> userRepository;
public LoginController(IRepository<User> userRepository)
{
this.userRepository = userRepository;
}
public bool Login(string username, string password)
{
var users = userRepository.GetAll();
return users.Any( user =>
user.UserName.Equals(username, StringComparison.InvariantCultureIgnoreCase) &&
user.Password.Equals(password));
}
}
Following is the system we would like to test. The problem is that we have to stub the userRepository to be able to create an instance of LoginController and test the login method. In C# I would use a framework like Rhino Mocks or Moq, but how do we tackle this problem in F#?
[<Fact>]
let ShouldSuccessfullyLoginToController() =
// Setup
let user = new User("Mikael", "Hello")
let repository = {
new IRepository<User> with
member this.GetAll() = [|user|] :> seq<User> }
let controller = new LoginController(repository)
// Test
let result = controller.Login(user.UserName, user.Password)
// Assert
Assert.True(result)
In F# we can generate concerete instances of any abstract class or interface with object expressions. This is very useful when creating test doubles in testdriven development, since we no longer have any use for stubbing frameworks - only mocking.
Daniel Mohl has written a couple of extensions that will help you getting started with F# web development. You'll find them in the Tools/Extension Manager within Visual Studio. Select the Online tab and search for Daniel Mohl to find all of his extensions available.
With Daniel Mohl's extension installed you should be able to create a new F# ASPNET project from the Add New Project menu.
The project created is the same project that you would create for a C# MVC site, but with F# libraries instead. The route setup is translated into F# as with the model binders.
namespace LiteMedia.Web open System.Web open System.Web.Mvc [<HandleError>] type HomeController() = inherit Controller() member x.Index () : ActionResult = x.ViewData.["Message"] <- "Welcome to ASP.NET MVC!" x.View() :> ActionResult member x.About () = x.View() :> ActionResult
Our HomeController is very simple and it displays how to write the index and about methods. Nothing here that is suprising. Very simplistic code and yet everything that comes with the original C# version of this example site.
[<ServiceContract(ConfigurationName = "IsItFriday", Namespace = "http://litemedia.se/IsItFriday")>] [<ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)>] type public IsItFriday() = class [<OperationContract>] member public x.Query() = DateTime.Today.DayOfWeek = DayOfWeek.Friday end
let host = new ServiceHost( typeof<IsItFriday>,
[|new Uri("http://localhost:18889/")|]);
host.Open();
Writing a WCF web service in F# is pretty straight forward since web services is all about functions and not preserving state.
let fibonacci = Seq.initInfinite (fun i -> let rec fibonacci_inner = function | 0 -> 0 | 1 -> 1 | n -> fibonacci_inner (n - 1) + fibonacci_inner (n - 2) fibonacci_inner i)
val fibonacci : seq<int>
val it : seq<int> = seq [0; 1; 1; 2; ...]
let primes n = let rec sieve = function | [] -> [] | head :: tail -> head :: sieve (tail |> List.filter (fun x -> x % head <> 0)) sieve [2..n]
primes 100
val it : int list = 2; 3; 5; 7; 11; 13; 17; 19; 23; 29; 31; 37; 41; 43; 47; 53; 59; 61; 67; 71; 73; 79; 83; 89; 97]
More information about F# can be found at the Microsoft MSDN site. Tools for creating this presentation where S5 from Eric Meyer and SyntaxHighlighter by Alexander Gorbatchev.
Happy coding!