-->

dev fsharp

It’s hard to accustomed to F# notation after getting used to OO languages like C#. Today I’ll work on the advanced section of the TryFSharp.org site. As I go forward the concepts are taking longer and becoming harder to grasp!

Notes

  • Currying is an interesting concept. It means you don’t have to provide all of the arguments when calling a function. for example

An addition function can be defined as

let add x y = x + y

and another function using this definition can be defined as

let addFive = add 5

In this case addFive returns another function which is waiting for the rest if the arguments. For example the following code snippet prints 17

let add x y = x + y
let addFive = add 5
printfn "%d" (addFive 12)
  • Operators can be overloaded but it should be used with care as it may make the code obfuscated in some cases
type Point(x:float, y:float) =
  member this.X = x
  member this.Y = y

  static member (+) (p1:Point, p2:Point) = 
      new Point(p1.X + p2.X, p1.Y+p2.Y)

let p1, p2 = new Point(0., 1.), new Point(1.,1.)
p1 + p2
  • Active Patterns allow to wrap arbitrary values in a union-like data structure for easy pattern matching.

For example:

let (|Even|Odd|) n =
    if n % 2 = 0 then
        Even
    else
        Odd

In this case Even and Odd are union constructors, so our active pattern either returns an instance of Even or an instance of Odd.

Conclusion

Today I completed the first 2 sections of Advanced section in TryFSharp.org, only 2 more to go. Even though I’m planning to finish all the material in the site it feels like the advanced topics are not covered in depth. The examples provided are too complex for an absolute beginner. I found the F# Programming Wiki as a better resource for these topics and I’m now going over both these resources.

Resources

dev fsharp

Yesterday I started devoting 2 pomodoros a day on learning F#. I will post my findings as I go along. Currently I’m on my second day and still working TryFSharp.org tutorial website. I think these notes will come in handy in the future so I decided to post them regularly.

What I’ve learned today

  • Record types can be defined by type keyword such as
type Book = 
  { Name: string;
    AuthorName: string;
    Rating: int;
    ISBN: string }

New objects of type Book can be created by let bindings

let expertFSharp = 
  { Name = "Expert F#";
    AuthorName = "Don Syme, Adam Granicz, Antonio Cisternino";
    Rating = 5;
    ISBN = "1590598504" }  

These values are immutable but new objects can be created based on the current values:

let partDeux = { expertFSharp with Name = "Expert F# 2.0" }

If there are similar types F# will infer the last one defined. So when there are duplicate types it may be needed to use explicit definitions. For example

let expertFSharp = 
  { Name = "Expert F#";
    AuthorName = "Don Syme, Adam Granicz, Antonio Cisternino";
    Book.Rating = 5;
    ISBN = "1590598504" }  

In the above example Rating is referred explicitly by using the dot notation so that the correct type can be resolved.

  • Option types represent data that may or may not exist. There are two types: Some and None. Some is used when the data does exist and None is used when it doesn’t.
type Book =
  { Name: string;
    AuthorName: string;
    Rating: int option;
    ISBN: string }

Now Rating value is optional can be assigned None

Rating = None;
  • Discriminated Unions are equivalent of enums in C# and they can be defined by listing pipe-separated values:
type MushroomColor =
| Red
| Green
| Purple

Basics are covered in 4 sections in TryFSharp.org and this concludes the notes for the basics section. Next section is called Advanced F# Programming is composed of 5 sections. Tomorrow in my alloted time I’ll be looking into these sections.

Resources

dev fsharp

I’m not a big fan of New Year’s resolutions. I was meaning to start learning F# and since it’s the new year’s 2nd day it might a good time to finally give it a shot!

Where to start

It’s always hard to find the best resource when you are starting. Some time ago I heard about a Microsoft Research project called TryFSharp.org. It’s a tutorial website geared towards the absolute beginners. It comes with a REPL editor so no extra tools are needed to start.

From now on I’m planning to spend 2 pomodoros (around 1 hour) every day to learn F#. After my first 2 pomodoros I completed the first 3 sections and below are my notes for today’s training.

Lecture Notes

  • let keyword to bind names to values. These bindings are immutable. If you try to assign a value to a same name twice you get the following error:
let duplicated = "original value"
let duplicated = "new value"

causes the following error:

stdin(8,5): error FS0037: Duplicate definition of value 'duplicated'
  • Mutable variables can be created by explicitly specifiying mutable keyword but it should be used cautiously.
  • F# is a statically typed language like C#
  • printfn can be used to display messages. Strings can be formatted by using special characters such %d for int, %s for string such as
printfn "The answer is %d" 42
  • let can also be used bind a name to a function. The following code
let square x =
    x * x

square 4

produces this result in the output window:

> let square x =
      x * x
  
  square 4

val square : x:int -> int
val it : int = 16

> 
  • F# is whitespace-sensitive. In the function above the body of the function was denoted by indenting it 4 spaces and return values is the last line of the function.
  • In times when F# cannot determine the type on itw own, it can specified explicitly bu using type annotations. For example:
let toLeetSpeak (phrase:string) =
    phrase.Replace('t', '7').Replace('o', '0')

toLeetSpeak "root"

In the example above it needs to be specified that phrase if of type string before String.Replace method can be called.

  • Functions can be defined inside other functions:
let quadruple x =    
    let double x =
        x * 2

    double(double(x))
  • A function can be used as an argument to another function to create what’s called a higher order function.
  • Inline functions can be created such as
let square = (fun x -> x * x)

Theres are called lambda functions or lambdas.

  • Lists can be created by semi-colon separated single values or a range values with .. in between such as
let evens = [2; 4; 6; 8]
let firstHundred = [0..100]
  • Higher-order functions can be combined with other functions such as
let firstHundred = [0..100]
List.map (fun x -> x * 2) 
    (List.filter (fun x -> x % 2 = 0) firstHundred)

which produces the following output

val it : int list =
  [0; 4; 8; 12; 16; 20; 24; 28; 32; 36; 40; 44; 48; 52; 56; 60; 64; 68; 72; 76;
   80; 84; 88; 92; 96; 100; 104; 108; 112; 116; 120; 124; 128; 132; 136; 140;
   144; 148; 152; 156; 160; 164; 168; 172; 176; 180; 184; 188; 192; 196; 200]

It first filters the odd numbers out of firstHundred list and send the result to map function to double all the values.

  • Forward-pipe operator can be used to make the code easier to read when functions are chained:
[0..100]
|> List.filter (fun x -> x % 2 = 0)
|> List.map (fun x -> x * 2)
|> List.sum
  • Array indexing is zero-based.

Resources