Fsharp

This is the second part of a series of posts about functional paradigm and its usefulness in nowadays business applications. As mentioned in the previous post, we will be learning the basics of F# language, the functional choice of Microsoft for the .NET ecossystem. The idea of this post is to have a 15 minute pitch of F# usefulness before going deeper into it.

Benefits

If you are a long time C# or Java developer, you may be wondering why would be worth learning another language. Or you already heard about functional and want to see if F# is a good spot. Regardless, F# has some great benefits under several areas that might catch your attention.

1. Conciseness. Write less code, avoid unecessary things. You don't need to write so much code just to meets the standard of the language, or the compiler. You don't see so much "noise" when coding, like curly bracktes and semicolons. Most of them are not necessary or optional.

// Type inference: F# deduces types automatically
// We will see later how it works: F# still is a static typed language!
let one = 1
let joe = "Joe"

// Functions: no curly braces, semicolons or parentheses
let sum a b = a + b
let five = sum 2 3

// If you need a context, they are separated by identation
// The last computed value (a + b) is always the return value
let sumAndLog a b =
    printfn "Adding %d to %d" a b
    a + b

2. Convenience. Common time consuming tasks are way easier and faster to do in F#. We can create complex type definitions, list processing, equality of complex objects, state machines and more in just a few lines. Functions are also treated as objects, so we can use them as arguments to other functions and get a whole new level of code reuse.

// Simple types can be defined in one line (or more, if you wish)
// This is a record type
type Person = { FirstName: string; LastName: string }

// Complex types can be created in few (if not one) lines
// This is a Discriminated Union, which uses Person and itself types to
// define a Employee entity: it can be a worker (in which case we have
// its Person definition attached to it), or a Manager of Employees
// (recursively reusing his own type)
type Employee =
    | Worker of Person
    | Manager of Employee list

// Obviously, type inference works for our new created types aswell!
let jdoe = { FirstName = "John"; LastName = "Doe" }
let worker = Worker jdoe

// Equality of many structures are already implemented by default
let person1 = { FirstName = "John"; LastName = "Doe" }
let person2 = { FirstName = "John"; LastName = "Doe" }
let person3 = { FirstName = "John"; LastName = "Arthur" }

printfn "person1 equals person2? %b" (person1 = person2) // true
printfn "person1 equals person3? %b" (person1 = person3) // false

// Working with lists is easy. Lets sum all numbers from 1 to 100
[1..100] |> List.sum |> printfn "Sum is %d"

// Operators are functions and can be used like them: first its name,
// and after it, its arguments - because they are not used by default
//  in this form, we need to put their name in parentheses
// Here is an example of partial application: you can define a new
// function by calling an existent one, and passing less arguments -
// the remaining ones will be the arguments of our new function
let add2 = (+) 2 // adds 2 to a number
let times3 = (*) 3 // multiplies 3 to a number

// We can easily compose new functions from older ones
// For example, to create a function that adds 2 to a number and after it
// multiplies 3, just use the composition parameter
let add2times3 = add2 >> times3
let nine = add2times3 1 // (1 + 2) * 3

2. Correctness. F# type system is really powerful. It prevents many common errors, like null reference exceptions. It's relatively easy to encode business logic into type definition, so we enter into a state that our code does not allow objects which are in an invalid state. And it is done in design time, so we can't even write incorrect code. The compiler itself helps us maintaining our BL!

// Strict type checking: wrong format strings causes compiler errors
// This causes a compiler error: token "%s" needs a string type
printfn "print string %s" 123

// Immutability by default: we don't modify states - we create new objects
// from old ones
let person1 = { FirstName = "John"; LastName = "Doe" }

person1.FirstName <- "Leon" // Error
person2 = { person1 with FirstName = "Leon"} // Leon Doe

// You almost never will have to check for nulls anymore!
// Even strings by default can always be appended to safely
let hello name = "Hello, " + name

// We can use units of measure to help us describing our data better
[<Measure>] type km
[<Measure>] type h

let distance = 10<km>
let time = 2<h>

// This code produces a compiler error: we cant add time to distance!
let invalid = 5<km> + 4<h>

// This code works, tough: if we travel 10 quilometers in 2 hours,
// we traveled in a velocity of 5 quilometers per hour - this is described
// by a automatic new unit of measure derived from our older ones (km/h)
let velocity = distance / time 

// We can even use this unit of measure directly!
let v = 10<km/h>

// Discriminated unions are powerfull to describe domain or business logic
// We can define type aliases, just to describe domain better,
// or enclose more validation rules if needed
type CreditCardNumber = string
type SecurityCode = string

[<Measure>] type USD

type PaymentMethod =
    | CreditCard of CreditCardNumber * SecurityCode
    | Cash

type Payment = { Method: PaymentMethod; Amount: decimal<USD> }

let myPayment = 
    { Method = CreditCard ("1234 5678 9012 3456", "999")
      Amount = 126.30m }

3. Concurrency features. It's relatively easy to work with parallelism, asynchronism and concurrency. Also, F# does have a native actor model, and support for event handling and reactive programming.

// Easy async logic through computation expressions - we will see it
// better laters
let result = async { return (1 + 2) }

// Easy parallelism - fibonnaci of numbers from 1 to 40
let result =
    Async.Parallel [ for i in 0..40 -> async { return fibonnaci(i) } ]

// Message queues are also easily implemented
// Below we define a message queue which process string messages and
// print them to the screen, asynchronously
let box = MailboxProcessor.Start (fun inbox -> async {
    let! msg = inbox.Receive()
    printfn "Message received: %s" msg })

box.Post("Hello World!")

3. Completeness. As already said before, F# is a functional-first language. It suppports other styles which are not 100% pure functional, making it easier to interact with other technologies. Because it is designed to be a hybrid language, it works under the same CLI of C#: not only it can do virtually everything C# does, but also F# assemblies can be used by C# code and vice-versa. Every .NET CLI assembly is accessible to us, and we can use them whenever we need.

// We can have mutable objects when needed
let mutable counter = 0

// We can create C# compatible classes and implement interfaces
// We can replicate IEnumerator interface exactly, for example
type IEnumerator<'a> =
    abstract member Current : 'a
    abstract MoveNext : unit -> bool

// Extension methods are also here!
type System.Int32 with
    member this.IsEven = this % 2 = 0

let number = 20
if number.IsEven then printfn "%d is even" number

// We can make windows forms applications with F#
open System.Windows.Forms

let form =
    new Form(Width = 400, Height = 300, Visible = true, Text = "Form1")

// Assignment operator
form.TopMost <- true

// Adding event handlers is easy too
form.Click.Add(fun args -> printfn "Click!")

form.Show()

Syntax

Here is a quick recipe on how to use F# syntax. With this, newcomers can quickly get used to it. I am not using very detailed information, and do not worry if you don't understand everything yet. Future posts will explain better those features.

// Single line comment

(* Multi line comment
   Line two of comment *)

// "let" keyword defines a value - immutable by default
let five = 5
let pi = 3.14
let name = "Ismael"

// Functions are also treated as values, so we define them
// by using "let" keyword too
let square n = n * n
let four = square 2

// As said before, multiline functions dont need semicolons or
// symbols to delimit their scope. Just use identation
// We also can have functions inside functions, closed to their
// scope, and use functions as parameters: List.filter applies
// a function that receives one element and decides if it should
// be added to a new, returned list
let evens list =
    let isEven x = x % 2 = 0
    list |> List.filter isEven

// Lists and list comprehensions
// Square brackets, separated by semicolons makes lists
let twoToFive = [2; 3; 4; 5]

// You can easily prepend or append values to create new lists
// by using the :: operator
// Lists are immutable by default, like other types
// So this is a new list created from 1 and twoToFive
let oneToFive = 1 :: twoToFive // [1; 2; 3; 4; 5]

// You can also connect lists to create new ones
// by using the @ operator
let zeroToFive = [0; 1] @ twoToFive

// Functions can be chained together in a easy readable way
// Imagine a function that receives a list of integers,
// apply square to them and then sum them all
// We could use List.sum and List.map to do it like we are used to
let sumOfSquaresTo100 =
    // List.map creates a new list from an existing one, applying
    // the function of the first parameter to each element of the
    // list of the second parameter
    let squares = List.map square [1..100]
    // Now we sum our squares and return it
    List.sum squares

// We could implement this in one line, using parenthesis to 
// enclose the second parameter code to generate squares list
// Its important to understand the necessity of parenthesis:
// If we dont use them, List.sum will take List.map function
// definition as an argument, not the entire operation
// This is because we dont use semicolons to pass funciton
// parameters in F#
let betterSumOfSquaresTo100 =
    List.sum (List.map square [1..100])

// Now there we have an even easier way to do it, and it becomes
// more read friendly. The "|>" operator takes a value in the left
// and applies as the last parameter of a function call
let evenBetterSumOfSquaresTo100 =
    [1..100] |> List.map square |> List.sum

// You can also create anonymous function lambdas with "fun"
let sumOfSquaresTo100WithLambda =
    [1..100] |> List.map (fun x -> x * x) |> List.sum

// Pattern matching
// Pattern matching is like a better switch/case statement
let stringAnalyser str =
    match str with
    | "a" -> printfn "str is a"
    | "b" -> printfn "str is b"
    | s when s.StartsWith("a") -> printfn "str starts with a"
    | _ -> printfn "str is something else" // "_" matches everything

// Discriminated Unions represent choices
// We define choices with pipes
type Temp =
    | DegreesC of float
    | DegreesF of float

let temp = DegreesC 98.6 // A way to represent 98.6 Celsius

// We don't use null by default
// We use a special Discriminated Union for this: Option
// Already in FSharp.Core, don't need to implement this!
type Option<'a> =
    | Some of 'a
    | None

let presentValue = Some 12 // Option<int>
let missingValue = None

// Discriminated Unions should be read with pattern matching,
// And we need to treat all cases. We can't forget to treat null
// values this way!
let seeIfIsPresent value =
    match value with
    | Some i -> printfn "Value is present: %i" i
    | None -> printfn "Value is missing!"

seeIfIsPresent presentValue // prints "Value is present: 12"
seeIfIsPresent missingValue // prints "Value is missing!"

// Printing values to console can be done by using
// printf and printfn - they work like Console.Write and
// Console.WriteLine, respectively
// They enforce type checking in string patterns
printfn "Printing an integer %d, a float %f and bool %b" 1 2.0 true

// %A receives anything. If it is an F# type, it does pretty
// printing (a list would print every element of it, for example)
// If it is not an F# type, it calls .ToString() method of the type
printfn "A sring %s and something generic %A" "hello" [1; 2; 3]

// We also have a function that works the same way for string
// formatting, like String.format - sprintf
let hello name = sprintf "Hello, %s" name

Next steps

Oh my, this was a considerable amount of sample code to a post. On the next series of posts, we will be talking a bit deeply about functions: the central element of the functional paradigm. If you are liking F# so far, keep trying it. Don't forget to see F# for fun and profit if you want to speed up your learning process.