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
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
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
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
|