Introduction to F#

Very Brief Introduction to F# language

Scripting

F# supporting something called Scripting. Even thought we are going to write our code in .fs files only. But you can always create .fsx file and run things in interactive. Go ahead and create tour.fsx file in src\Client folder.

You can also checkout the chapter-1 branch from https://github.com/kunjee17/hello-elmish-app and find that file.

Tour of F\

If you like to have detailed tour of F# then you should check out detailed document on MSFT site. You can copy paste code and send to interactive to run. And play around it.

Here we will check out very few things from that. Very basic core concepts that would be required for Elmish Application.

Core Concepts

Types

F# is typed language, so everything is very much strictly typed.

5 = "5" // Not going to work like other front end language

F# supports inferred types. So, you can or can not define types.

let foo = "bar"
let foo':string = "bar"

Both are valid.

but

let foo'':string = 5

is not valid

I can talk about types for whole book, instead we will move fast and learn thing as and when needed.

Record Type & Union Type

As per docs Records are an aggregate of named values, with optional members (such as methods).. It is basically bounded context. If we simplify that is thing it is very similar to POCO or POJO from C# or Java. They are not exact same but similar.

Here is simple example

type Login = {
Username : string
Password : string
}

This is how you define simple record type.

let login = {Username = "Kunjee"; Password = "password"}

And this how your create immutable object. Immutable means you can't change it after words. And if you want to change that value then you have to create new value.

let login1 = {login with Password = "password123"}

Another thing we gonna use extensively is Union type.

Let's check out the example.

type Gender = Male | Female | Other
let male = Male

And you can always pattern matching on Union type.

let printGender (gender: Gender) =
match gender with
| Male -> printfn "male is here"
| Female -> printfn "female is here"
| Other -> printfn "other is here"
printGender male //male is here

Immutability

Immutability is the one of best thing by default in most of the functional programming language. You can't change the value once assigned.

Let's visit above example again

type Login = {
Username : string
Password : string
}
let login = {Username = "Kunjee"; Password = "password"}
let login1 = {login with Password = "password123"}

login1 is completely different object from login. So, a new object created every time we want to change something in model or object.

Immutability normally don't hurt performance but helps us to get faster. Explaining why is not in context of this book.

Mutability is there in F#.

let mutable login3 = "foo"
login3 <- "bar"

We should avoid mutability. It is for special case only. We will not use it in Elmish tutorial.

Functions

We are using Functional Programming. And What is functional programming without Functions ?

F# also have functions.

let add a b = a + b
add 2 3 //5

Simple most function. Here as per definition every function in F# is taking single argument and return a value or function that also take single argument.

If you don't get it then don't worry. It is a function taking two parameter and returning result. It is good for now. It works and I guess that is first thing that matters.

Partial Functions

If you don't get it at first don't worry. You will understand after using it.

We did touch this in in above section. Let's check that thing again.

Here are two simple functions

let add a b = a + b
let multiple a b = a * b

Very simple functions from Mathematics. add will add two variables and multiple will add two variables. Nothing new here. Other than syntax part it is very much same as OOP languages like Java, C#, C++ etc.

Now, look at the below code. And you might get surprised by code.

let add a b = a + b
add 2 3 //5
let multiply a b = a * b
multiply 2 3 //6
let add1 = add 1
add1 4 //5
let add2 = add 2
add2 4 //6
let multiplyAndAdd a b = multiply a b |> add (add a b)
multiplyAndAdd 2 3 //11
let add3 x = (add1 >> add2) x
add3 4 //7

First two functions are simple enough and we had go through that. Now add1 is very typical use case for partial function. If we look at the definition closely if is nothing but add with one parameter. So, just for understanding purpose it is add function with one missing parameter. And that we will assign to add1 so by definition it should be taking that missing one parameter. So, add1 is adding 1 to any given parameter. Or we can say add1 is passing second parameter other to add function other than 1.

If you don't get it, don't worry. It will become normal after using it couple of times.

add2 is doing the same thing but with 2.

Now, this ability to take only half parameter and passing / assigning functions as value can open up interesting possibilities for code.

You can do things like multiplyAndAdd. In that function first we are multiplying the given parameters. And then passing result of that as second value of parameter to add function; where first parameter is (add a b) function it self.

We can also combine two functions if one functions output is matches another functions input. add3 function is doing the same thing. It is using >> operator to combine two functions add1 and add2. In words add3 will take input x and pass it to add1 and then take output of that operation and pass it as input to add2 and then return result of that function.

If we unwrap >> operator then it looks something like this

let join f g x = f (g x)
let add3' x = (join add1 add2) x
add3' 4 //7

If things seems little bit confusing then we can always use pipe forward (|>) operator.

let add3'' x= add1 x |> add2
add3'' 4 //7

All will give same result.

Just to make things more concise (of confusing) we can do same thing without parameter as in any case it will return function that will take single parameter

let add3''' = add1 >> add2
add3 4 //7

Partial application looks too much mathematically or confusing don't worry. I personally took around 2 years to get my head around that. It will come eventually. You will be using them successfully even before you know it.

Extras

Some more code to show use of Pipe Forward operators |>. As we will gonna use the quite a lot.

Let's first define list of numbers

let numbers = [1..10]

Now let's add 1 to every number in list

numbers |> List.map (fun x -> x + 1)

Let's try getting total of list

numbers |> List.fold (fun a b -> a + b) 0

Let's make it simple

numbers |> List.fold (+) 0

Let's make it even more simpler

numbers |> List.sum

Going into more detail of language is again out of scope for this book. So, I highly recommended to that one should took tour of F# for above link. You should always have fun with F#. Trust me having fun is way more important then understanding Lambdas or Monads.