val simpleValue : int

Full name: index.simpleValue
val factorial : x:int -> int

Full name: index.factorial
val x : int
Multiple items
module List

from Microsoft.FSharp.Collections

--------------------
type List<'T> =
  | ( [] )
  | ( :: ) of Head: 'T * Tail: 'T list
  interface IEnumerable
  interface IEnumerable<'T>
  member GetSlice : startIndex:int option * endIndex:int option -> 'T list
  member Head : 'T
  member IsEmpty : bool
  member Item : index:int -> 'T with get
  member Length : int
  member Tail : 'T list
  static member Cons : head:'T * tail:'T list -> 'T list
  static member Empty : 'T list

Full name: Microsoft.FSharp.Collections.List<_>
val reduce : reduction:('T -> 'T -> 'T) -> list:'T list -> 'T

Full name: Microsoft.FSharp.Collections.List.reduce
val reversePipe : int

Full name: index.reversePipe
val composition : (int -> int)

Full name: index.composition
val optional : int option

Full name: index.optional
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<_>
type 'T option = Option<'T>

Full name: Microsoft.FSharp.Core.option<_>
union case Option.None: Option<'T>
namespace System
Multiple items
type Result =
  | Even of int
  | Odd of int

Full name: index.Result

--------------------
type Result<'T,'TError> =
  | Ok of 'T
  | Error of 'TError

Full name: Microsoft.FSharp.Core.Result<_,_>
union case Result.Even: int -> Result
union case Result.Odd: int -> Result
val agentLogic : inbox:MailboxProcessor<AsyncReplyChannel<Result>> -> Async<'a>

Full name: index.agentLogic
val inbox : MailboxProcessor<AsyncReplyChannel<Result>>
Multiple items
type MailboxProcessor<'Msg> =
  interface IDisposable
  new : body:(MailboxProcessor<'Msg> -> Async<unit>) * ?cancellationToken:CancellationToken -> MailboxProcessor<'Msg>
  member Post : message:'Msg -> unit
  member PostAndAsyncReply : buildMessage:(AsyncReplyChannel<'Reply> -> 'Msg) * ?timeout:int -> Async<'Reply>
  member PostAndReply : buildMessage:(AsyncReplyChannel<'Reply> -> 'Msg) * ?timeout:int -> 'Reply
  member PostAndTryAsyncReply : buildMessage:(AsyncReplyChannel<'Reply> -> 'Msg) * ?timeout:int -> Async<'Reply option>
  member Receive : ?timeout:int -> Async<'Msg>
  member Scan : scanner:('Msg -> Async<'T> option) * ?timeout:int -> Async<'T>
  member Start : unit -> unit
  member TryPostAndReply : buildMessage:(AsyncReplyChannel<'Reply> -> 'Msg) * ?timeout:int -> 'Reply option
  ...

Full name: Microsoft.FSharp.Control.MailboxProcessor<_>

--------------------
new : body:(MailboxProcessor<'Msg> -> Async<unit>) * ?cancellationToken:Threading.CancellationToken -> MailboxProcessor<'Msg>
type AsyncReplyChannel<'Reply>
member Reply : value:'Reply -> unit

Full name: Microsoft.FSharp.Control.AsyncReplyChannel<_>
val odd : (int -> Async<'b>)
val counter : int
val async : AsyncBuilder

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.async
val msg : AsyncReplyChannel<Result>
member MailboxProcessor.Receive : ?timeout:int -> Async<'Msg>
member AsyncReplyChannel.Reply : value:'Reply -> unit
val even : (int -> Async<'b>)
val agent : MailboxProcessor<AsyncReplyChannel<Result>>

Full name: index.agent
val getNext : unit -> Result

Full name: index.getNext
member MailboxProcessor.PostAndReply : buildMessage:(AsyncReplyChannel<'Reply> -> 'Msg) * ?timeout:int -> 'Reply
val id : x:'T -> 'T

Full name: Microsoft.FSharp.Core.Operators.id
type internal Token = int

Full name: index.Token
type internal ThrottlingAgentMessage<'t> =
  | GetToken of AsyncReplyChannel<Token>
  | ReturnToken of Token

Full name: index.ThrottlingAgentMessage<_>
union case ThrottlingAgentMessage.GetToken: AsyncReplyChannel<Token> -> ThrottlingAgentMessage<'t>
union case ThrottlingAgentMessage.ReturnToken: Token -> ThrottlingAgentMessage<'t>
Multiple items
type ThrottlingAgent =
  new : limit:int -> ThrottlingAgent
  member GetToken : unit -> Token
  member ReturnToken : token:Token -> unit

Full name: index.ThrottlingAgent

--------------------
new : limit:int -> ThrottlingAgent
val limit : int
val agent : MailboxProcessor<ThrottlingAgentMessage<obj>>
val blocked : (unit -> Async<'a>)


 Represents a state when the agent is blocked - uses 'Scan' to wait for completion of some work
member MailboxProcessor.Scan : scanner:('Msg -> Async<'T> option) * ?timeout:int -> Async<'T>
val t : Token
union case Option.Some: Value: 'T -> Option<'T>
val hasCapacity : (int -> Async<'a>)


 Represents a state when the agent has capacity
val inUse : int
val msg : ThrottlingAgentMessage<obj>
val x : ThrottlingAgent
member ThrottlingAgent.GetToken : unit -> Token

Full name: index.ThrottlingAgent.GetToken
member ThrottlingAgent.ReturnToken : token:Token -> unit

Full name: index.ThrottlingAgent.ReturnToken
val token : Token
member MailboxProcessor.Post : message:'Msg -> unit
val i : int
val testNumber : i:int -> unit

Full name: index.testNumber
Multiple items
union case Result.Even: int -> Result

--------------------
active recognizer Even: int -> Choice<unit,unit>

Full name: index.( |Even|Odd| )
val printfn : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
Multiple items
union case Result.Odd: int -> Result

--------------------
active recognizer Odd: int -> Choice<unit,unit>

Full name: index.( |Even|Odd| )
val by : int
val n : int
val fizzBuzz : _arg1:int -> string

Full name: index.fizzBuzz
active recognizer DivisibleBy: int -> int -> unit option

Full name: index.( |DivisibleBy|_| )
Multiple items
val string : value:'T -> string

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

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

Full name: Microsoft.FSharp.Core.string
Multiple items
type MeasureAttribute =
  inherit Attribute
  new : unit -> MeasureAttribute

Full name: Microsoft.FSharp.Core.MeasureAttribute

--------------------
new : unit -> MeasureAttribute
[<Measure>]
type m

Full name: index.m
[<Measure>]
type sec

Full name: index.sec
[<Measure>]
type kg

Full name: index.kg
val distance : float<m>

Full name: index.distance
val time : float<sec>

Full name: index.time
val speed : float<m/sec>

Full name: index.speed
val acceleration : float<m/sec ^ 2>

Full name: index.acceleration
val force : float<kg m/sec ^ 2>

Full name: index.force
val travel : float<m>

Full name: index.travel

What is F#?

  • ML / OCaml derivative (influenced by Haskell & Erlang)
  • Influencing F*, Elm ( Elmish ), C# (Linq,async/await)
  • Open source since 2005: FSharp.org & Github
  • Functional First but very pragmatic
  • Supports Actor model & OO
  • Infers Types
  • Used a lot in finance (correctness + speed), but general purpose language

Examples

1: 
2: 
3: 
4: 
5: 
6: 
7: 
let simpleValue = 5
let factorial x = [1..x] |> List.reduce (*)

let reversePipe = factorial <| 1+2      // $ in haskell
let composition = factorial >> ((+) 1)  // . in haskell

let optional: int option = None         // Maybe in haskell

F# cheatsheet

5 things beyond FP

  • It runs everywhere
  • Linear dependancies
  • Light weight actors
  • Active Patterns
  • Type providers

Where can you run F# ?

  • Mac, Linux, Windows, FreeBSD (mono or .net core)
  • Android, iPhone
  • GPU
  • Cloud functions (AWS Lambda, Azure Functions)
  • MBrace
  • Juptier notebooks
  • Spark
  • Javascript

Atwood's Law: any application that can be written in JavaScript, will eventually be written in JavaScript.

Linear Dependancies

  • Compiles top to bottom, left to right, single pass
  • Annoying at First
  • Grown to love the constraint
  • Foundations first, type driven development
  • Leads to less coupled code, less cyclic dependancies

Tickflow

Shamlessly copied from FSFFAP Tickflow

Specflow

Specflow

Light Weight Actors

  • Good for state diagrams, thread safety
  • Post and Receive, sync or async, timeouts
  • Supports thousands of them
  • Async pool
Examples
  • Stateful
  • Bounded queue
  • Web Socket
 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
open System

type Result = Even of int | Odd of int 

let agentLogic (inbox:MailboxProcessor<AsyncReplyChannel<Result>>) =
    let rec odd(counter) = async {
        let! msg = inbox.Receive()
        msg.Reply(Odd counter)
        return! even(counter + 1)} 
        
    and even(counter) = async {
        let! msg = inbox.Receive()
        msg.Reply(Even counter)
        return! odd(counter + 1)}

    odd 1

let agent = MailboxProcessor<_>.Start agentLogic
let getNext () = agent.PostAndReply id
 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
type internal Token = int
type internal ThrottlingAgentMessage<'t> = 
    | GetToken of AsyncReplyChannel<Token>
    | ReturnToken of Token

type ThrottlingAgent(limit) = 
    let agent = MailboxProcessor<ThrottlingAgentMessage<_>>.Start(fun agent -> 
    
        /// Represents a state when the agent is blocked - uses 'Scan' to wait for completion of some work
        let rec blocked() = 
            agent.Scan(function ReturnToken t -> Some( hasCapacity (limit - 1)) | _ -> None) 
        
        /// Represents a state when the agent has capacity
        and hasCapacity inUse = async { 
            let! msg = agent.Receive()
            match msg with 
            | ReturnToken _  -> return! hasCapacity (inUse - 1))
            | GetToken resp  ->
                resp.Reply(1)
                if inUse < limit - 1 then return! hasCapacity (inUse + 1)
                else return! blocked() }
        hasCapacity 0)          // Start in working state with zero running work items
    member x.GetToken() = agent.PostAndReply( GetToken )
    member x.ReturnToken(token) = agent.Post( ReturnToken token )

Active Patterns

  • Abstraction over types

Complete patterns

1: 
2: 
3: 
4: 
5: 
6: 
7: 
let (|Even|Odd|) i = 
    if i % 2 = 0 then Even else Odd

let testNumber i =
    match i with
    | Even -> printfn "%d is even" i
    | Odd -> printfn "%d is odd" i

Parametised

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
let (|DivisibleBy|_|) by n = 
    if n % by = 0 then Some DivisibleBy else None

let fizzBuzz = function 
    | DivisibleBy 3 & DivisibleBy 5 -> "FizzBuzz" 
    | DivisibleBy 3 -> "Fizz" 
    | DivisibleBy 5 -> "Buzz" 
    | i -> string i

Type Providers

  • Removing magic strings
  • Irritating when the build breaks

CSV,JSON,XML,HTML: FSharp.data

Lots of them

  • Regular Expressions
  • AWS S3 / Azure storage
  • Databases (ORMS, querys, sprocs)
  • WMI
  • OData
  • Hadoop
  • Slack
  • R

Rogue One TP

silly silly2

Other stuff

  • Quotations: expression trees
  • Computation Expressions: Monads + DSLs
  • Units of measure
 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
[<Measure>] type m
[<Measure>] type sec
[<Measure>] type kg

let distance = 1.0<m>    
let time = 2.0<sec>    
let speed = 2.0<m/sec>    
let acceleration = 2.0<m/sec^2>    
let force = 5.0<kg m/sec^2>
let travel = time * speed