User Tools

Site Tools


technical_notes:public:fsharp-concept

Parent

F# - Concepts

Thoses concepts are extract from F# koan propose by Chris Marinos.

Variable affectation

Use let.

let AssertExpectation() =
        let expected_value = 1 + 1
        let actual_value = 2     

Types management

let YouCanMakeTypesExplicit() =
        let (x:int) = 42
        let typeOfX = x.GetType()
 
        let y:string = "forty two"
        let typeOfY = y.GetType()
 
        AssertEquality typeOfX typeof<int>
        AssertEquality typeOfY typeof<string>

Declare mutable variable

You have to use as operator.

let ModifyingTheValueOfVariables() =
        let mutable x = 100
        x <- 200

Function

Declare a function

let add x y =
    x + y

Declare a nested function

let quadruple x =    
    let double x =
        x * 2
 
    double(double(x))
 
let result = quadruple 4

Use dot Net method

let sayItLikeAnAuctioneer (text:string) =
    text.Replace(" ", "")

Use parenthesis to group function call

let add x y =
     x + y
 
     let result = add (add 5 8) (add 1 1)

Pipe backward

let add x y =
    x + y
 
let double x =
    x * 2
 
let result = double <| add 5 8

Implementation of <|

let (<|) func u = func u

Unit () (in place of void)

let sendData data =
    ()
 
let x = sendData "data"
//Don't overthink x == ()

Declare function that takes no Param (param Unit)

let sayHello() =
    "hello"
 
let result = sayHello()

Tuples

Create a new tuple

let items = ("apple", "dog")

Accessing elements in a tuple

let items = ("apple", "dog")
 
let fruit = fst items
let animal = snd items

Accessing elements through pattern matching

let items = ("apple", "dog", "Mustang")   
let fruit, animal, car = items

Accessing elements through partial pattern matching

let items = ("apple", "dog", "Mustang")
let _, animal, _ = items

Apply function through Pattern matching

let squareAndCube x =
    (x ** 2.0, x ** 3.0)
 
let result = squareAndCube 3.0

String

Sprintf

let message = sprintf "F# turns it to %d!" 11

Sprintf : format anything

let message = sprintf "Formatting other types is as easy as: %A" (1, 2, 3)
// Result : "Formatting other types is as easy as: (1, 2, 3)"

Combine multiline

let message = "super\
               cali\
               fragilistic\
               expiali\
               docious"
// Result : "supercalifragilisticexpialidocious"

Multiline

let message = "This
                is
                on
                five
                lines"

Extract characters

let message = "hello world"
 
let first = message.[0]
let other = message.[4] 

If : Branching

Basic

let isEven x =
    if x % 2 = 0 then
        "it's even!"
    else
        "it's odd!"
 
let result = isEven 2 

Statement returns value

let result = 
  if 2 = 3 then
      "something is REALLY wrong"
  else
      "no problem here"

Branching with Pattern matching

let isApple x =
    match x with
    | "apple" -> true
    | _ -> false
 
let result1 = isApple "apple"
let result2 = isApple ""

More complex branching with Pattern Matching

let getDinner x =
    match x with
    | (name, "veggies")
    | (name, "fish")
    | (name, "chicken") -> sprintf "%s doesn't want red meat" name
    | (name, foodChoice) -> sprintf "%s wants 'em some %s" name foodChoice 
 
let person1 = ("Bob", "fish")
let person2 = ("Sally", "Burger")
 
AssertEquality (getDinner person1) "Bob doesn't want red meat"
AssertEquality (getDinner person2) "Chris wants 'em some Burger"

List

In F#, the list are single linked list.

Create one list

let list = ["apple"; "pear"; "grape"; "peach"]

Difference with .Net

let list = []
let dotNetList = new List<string>()
AssertInequality (list.GetType()) (dotNetList.GetType())

Basic function on list

let list = ["apple"; "pear"; "grape"; "peach"]
 
AssertEquality list.Head "apple"
AssertEquality list.Tail ["pear"; "grape"; "peach"]
AssertEquality list.Length 4  

Append an element to create new list

let first_list = ["grape"; "peach"]
let second_list = "pear" :: first
let third_list = "apple" :: second

Concatenate lists together

let first = ["apple"; "pear"; "grape"]
let second = first @ ["peach"] // result : ["apple"; "pear"; "grape"; "peach"]

Creating a list using a range

let list = [0..4]

Creating a list using a generator

let list = [for i in 0..10 do 
              if i % 2 = 0 then yield i ]
 
// Result : [0;2;4;6;8;10]

Transform a list using a map

Apply a function on each element of the list.

let square x =
    x * x
 
let original = [0..5]
let result = List.map square original
 
// Result : [0;1;4;9;16;25]

Filter a list using filter

let isEven x =
    x % 2 = 0
 
let original = [0..5]
let result = List.filter isEven original

Divide list in 2 new list using Partition

let isOdd x =
    not(x % 2 = 0)
 
let original = [0..5]
let result1, result2 = List.partition isOdd original
 
//Result1:[1;3;5]
//Result2:[0;2;4]

Pipe

Using Forward Pipe |>

let result =
  [0..5]
  |> List.filter isEven
  |> List.map square

How the forward pipe is implemented ?

let (|>) x func =
  func x

Array

Create an array

The array content is mutable.

let fruits = [| "apple"; "pear"; "peach"|]

Array are .Net Array

let fruits = [| "apple"; "pear" |]
 
let arrayType = fruits.GetType()
let systemArray = System.Array.CreateInstance(typeof<string>, 0).GetType()
 
// arrayType and systemArray has the same value

Create an array using generator

let numbers = 
  [| for i in 0..10 do 
         if i % 2 = 0 then yield i |]
 
// Result : [|0;2;4;6;8;10|]
technical_notes/public/fsharp-concept.txt · Last modified: 2014/03/20 17:51 by Fabien Arcellier