val num : int

Full name: Index.num
val str : string

Full name: Index.str
val pi : float

Full name: Index.pi
val circleArea : r:float -> float

Full name: Index.circleArea
val r : float
namespace System
val getTomorrow : today:DateTime -> DateTime

Full name: Index.getTomorrow
val today : DateTime
Multiple items
type DateTime =
  struct
    new : ticks:int64 -> DateTime + 10 overloads
    member Add : value:TimeSpan -> DateTime
    member AddDays : value:float -> DateTime
    member AddHours : value:float -> DateTime
    member AddMilliseconds : value:float -> DateTime
    member AddMinutes : value:float -> DateTime
    member AddMonths : months:int -> DateTime
    member AddSeconds : value:float -> DateTime
    member AddTicks : value:int64 -> DateTime
    member AddYears : value:int -> DateTime
    ...
  end

Full name: System.DateTime

--------------------
DateTime()
   (+0 other overloads)
DateTime(ticks: int64) : unit
   (+0 other overloads)
DateTime(ticks: int64, kind: DateTimeKind) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, calendar: Globalization.Calendar) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, kind: DateTimeKind) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, calendar: Globalization.Calendar) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int, kind: DateTimeKind) : unit
   (+0 other overloads)
DateTime.AddDays(value: float) : DateTime
val tomorrow : DateTime

Full name: Index.tomorrow
property DateTime.UtcNow: DateTime
val x : int

Full name: Index.x
val y : int

Full name: Index.y
val add : x:int -> y:int -> int

Full name: Index.add
val x : int
val y : int
val add' : x:int -> y:int -> int

Full name: Index.add'
val add'' : x:int -> y:int -> int

Full name: Index.add''
val addNumbers : x:int -> y:int -> int

Full name: Index.addNumbers
val increment : (int -> int)

Full name: Index.increment
val calculate : f:('a -> 'b -> 'c) -> x:'a -> y:'b -> 'c

Full name: Index.calculate
val f : ('a -> 'b -> 'c)
val x : 'a
val y : 'b
val u : int

Full name: Index.u
val w : int

Full name: Index.w
val a : int

Full name: Index.a
val b : int

Full name: Index.b
val rest : int list

Full name: Index.rest
val aList : 'a list

Full name: Index.aList
val msg : string

Full name: Index.msg
val x : obj
val sprintf : format:Printf.StringFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
val y : obj
val eq1 : bool

Full name: Index.eq1
val field1 : string * int

Full name: Index.field1
val field2 : string * int

Full name: Index.field2
val eq2 : bool

Full name: Index.eq2
type Person =
  {Name: string;
   Age: int;}

Full name: Index.Person
Person.Name: string
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = String

Full name: Microsoft.FSharp.Core.string
Person.Age: int
Multiple items
val int : value:'T -> int (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.int

--------------------
type int = int32

Full name: Microsoft.FSharp.Core.int

--------------------
type int<'Measure> = int

Full name: Microsoft.FSharp.Core.int<_>
val m1 : Person

Full name: Index.m1
val m2 : Person

Full name: Index.m2
val eq3 : bool

Full name: Index.eq3
Multiple items
module Option

from Microsoft.FSharp.Core

--------------------
type Option<'a> =
  | Some of 'a
  | None

Full name: Index.Option<_>
union case Option.Some: 'a -> Option<'a>
union case Option.None: Option<'a>
val m : Option<int>

Full name: Index.m
val result : Option<int>

Full name: Index.result
val i : int

Agenda

  1. FP in Software Industry
  2. History
  3. Motivation
  4. Concepts
  5. Insights
  6. Demo

Functional Programming in software Industry

Functional Programming History

  • 1950s - Lisp by John McCarthy (MIT)
  • 1960s - APL by Kenneth E. Iverson (Harvard)
  • 1970s - ML by Robin Milner (University of Edinburgh)
  • 1986 - Erlang
  • 1990 - Haskell
  • 1996 - OCaml
  • 2004 - Scala
  • 2005 - F# by Don Syme
  • 2007 - Clojure
  • 2012 - Elm
  • 2014 - Swift

F# History

  • 2005 - first stable release (F# 1.0)
  • Don Syme - language designer
  • Open Source since 2010
  • Cross-platform
  • fsharp.org - F# official page

My Motivation

  • Broaden horizons
  • Productivity
  • Safety
  • Reliability
  • Robustness
  • Joy
  • Peace

Alan Perlis: a language that doesn't affect the way you think about programming, is not worth knowing.

F# Overview

  • Functional
  • Imperative
  • Object-Oriented
  • Asynchronous
  • Parallel
  • Agent model

Type inference

A mechanism used by compiler to deduce what types are used in expressions in a program.

Type inference

1: 
2: 
3: 
4: 
5: 
6: 
let num = 7
let str = "F# rocks!"
let pi = 3.14

let circleArea r = 3.14 * r ** 2.
circleArea 1.
3.14

Type inference - explicit annotations

1: 
2: 
3: 
4: 
open System
let getTomorrow (today: DateTime) =
    today.AddDays(1.)
let tomorrow = getTomorrow DateTime.UtcNow
24.09.2016 16:41:57

Immutability

  • no side-effects
  • no mutation of a state
  • no modifications of other parts of a program

Immutability

1: 
2: 
3: 
let x = 7
// x = x + 1 // WRONG!!
let y = x + 1 // GOOD
8

Currying

... means transforming a function with many arguments,

into a series of functions,

each with only one argument.

All functions in F# are auto-curried by compiler.

Currying

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
let add x y = x + y

let add' x = fun y -> x + y

let add'' =
    fun x ->
        fun y -> 
            x + y

Partial Application

... means passing to function less arguments

than it originally accepts.

As a result function returns another function,

which accepts remaining parameters.

Partial Application

1: 
2: 
3: 
4: 
5: 
let addNumbers x y = x + y

let increment = addNumbers 1

increment 3
4

Higher Order Functions

Functions which:

accept another function as an input,

or return function as an output.

Higher Order Functions

1: 
2: 
3: 
4: 
5: 
6: 
let calculate f x y =
    f x y

calculate (+) 3 4

calculate (*) 3 4
7
12

Pattern Matching

Pattern Matching I

1: 
2: 
3: 
let u, _, w = (1, 3, 5)
u
w
1
5

Pattern Matching II

1: 
2: 
3: 
4: 
let a::b::rest = [1..10] 
a
b
rest
1
2
[3; 4; 5; 6; 7; 8; 9; 10]

Pattern Matching III

1: 
2: 
3: 
4: 
5: 
6: 
7: 
let aList = []
let msg =
    match aList with
    | [] -> "empty" 
    | [x] -> sprintf "one item: %A" x 
    | [x; y] -> sprintf "two items: %A and %A" x y 
    | _ -> "many items"
"empty"

Structure Equality I

1: 
let eq1 = 4 = 3
false

Structure Equality II

1: 
2: 
3: 
let field1 = ("a", 3)
let field2 = ("a", 5 - 2)
let eq2 = field1 = field2
true

Structure Equality III

1: 
2: 
3: 
4: 
type Person = { Name: string; Age: int }
let m1 = { Name = "Mike"; Age = 22 }
let m2 = { Name = "Mike"; Age = 22 }
let eq3 = m1 = m2
true

Option Type

It is a union of two cases:

  • Data is present
  • Data is missing

Option Type

1: 
2: 
3: 
type Option<'a> =
| Some of 'a
| None  

Option Type

1: 
2: 
3: 
4: 
5: 
let m = Some 5
let result = 
    match m with 
    | Some i -> Some (i * 2)
    | None -> None
Some 10

F# Vital Statistics

Developer Survey Results 2016

by

StackOverflow logo

F# Vital Statistics - Most Loved

Most Loved category

F# Vital Statistics - Top Paying Tech US

Top Paying Tech US category

F# Vital Statistics - Top Paying Tech Worldwide

Top Paying Tech Worldwide category

Resources

Summary - F#

  • multi-paradigm (FP, OO)
  • flexible
  • powerful
  • functional-first

Summary - F# code

  • concise
  • clean
  • robust
  • safe
  • expressive
  • reusable
  • maintainable

F# Developer

Happy Dog image

Demo

Thank you!

@FSharpWalker