val getHtml : url:string -> 'a

Full name: index.getHtml
val url : string
Multiple items
val string : value:'T -> string

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

--------------------
type string = System.String

Full name: Microsoft.FSharp.Core.string
val req : obj
val response : obj
val streatm : System.IDisposable
val reader : System.IDisposable
val getHtmlA : url:string -> Async<'a>

Full name: index.getHtmlA
val async : AsyncBuilder

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.async
val getHtmlA : url:string -> 'a

Full name: index.getHtmlA
val req : 'a
val response : 'a
val streatm : 'a (requires 'a :> System.IDisposable)
val reader : 'a (requires 'a :> System.IDisposable)
union case Option.Some: Value: 'T -> Option<'T>
val printfn : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
namespace System
Multiple items
type Async
static member AsBeginEnd : computation:('Arg -> Async<'T>) -> ('Arg * AsyncCallback * obj -> IAsyncResult) * (IAsyncResult -> 'T) * (IAsyncResult -> unit)
static member AwaitEvent : event:IEvent<'Del,'T> * ?cancelAction:(unit -> unit) -> Async<'T> (requires delegate and 'Del :> Delegate)
static member AwaitIAsyncResult : iar:IAsyncResult * ?millisecondsTimeout:int -> Async<bool>
static member AwaitTask : task:Task<'T> -> Async<'T>
static member AwaitWaitHandle : waitHandle:WaitHandle * ?millisecondsTimeout:int -> Async<bool>
static member CancelDefaultToken : unit -> unit
static member Catch : computation:Async<'T> -> Async<Choice<'T,exn>>
static member FromBeginEnd : beginAction:(AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg:'Arg1 * beginAction:('Arg1 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * beginAction:('Arg1 * 'Arg2 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * arg3:'Arg3 * beginAction:('Arg1 * 'Arg2 * 'Arg3 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromContinuations : callback:(('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) -> Async<'T>
static member Ignore : computation:Async<'T> -> Async<unit>
static member OnCancel : interruption:(unit -> unit) -> Async<IDisposable>
static member Parallel : computations:seq<Async<'T>> -> Async<'T []>
static member RunSynchronously : computation:Async<'T> * ?timeout:int * ?cancellationToken:CancellationToken -> 'T
static member Sleep : millisecondsDueTime:int -> Async<unit>
static member Start : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
static member StartAsTask : computation:Async<'T> * ?taskCreationOptions:TaskCreationOptions * ?cancellationToken:CancellationToken -> Task<'T>
static member StartChild : computation:Async<'T> * ?millisecondsTimeout:int -> Async<Async<'T>>
static member StartChildAsTask : computation:Async<'T> * ?taskCreationOptions:TaskCreationOptions -> Async<Task<'T>>
static member StartImmediate : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
static member StartWithContinuations : computation:Async<'T> * continuation:('T -> unit) * exceptionContinuation:(exn -> unit) * cancellationContinuation:(OperationCanceledException -> unit) * ?cancellationToken:CancellationToken -> unit
static member SwitchToContext : syncContext:SynchronizationContext -> Async<unit>
static member SwitchToNewThread : unit -> Async<unit>
static member SwitchToThreadPool : unit -> Async<unit>
static member TryCancelled : computation:Async<'T> * compensation:(OperationCanceledException -> unit) -> Async<'T>
static member CancellationToken : Async<CancellationToken>
static member DefaultCancellationToken : CancellationToken

Full name: Microsoft.FSharp.Control.Async

--------------------
type Async<'T>

Full name: Microsoft.FSharp.Control.Async<_>
static member Async.Sleep : millisecondsDueTime:int -> Async<unit>
static member Async.RunSynchronously : computation:Async<'T> * ?timeout:int * ?cancellationToken:System.Threading.CancellationToken -> 'T
val sprintf : format:Printf.StringFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
val failwith : message:string -> 'T

Full name: Microsoft.FSharp.Core.Operators.failwith
Multiple items
val byte : value:'T -> byte (requires member op_Explicit)

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

--------------------
type byte = System.Byte

Full name: Microsoft.FSharp.Core.byte
Multiple items
module List

from Microsoft.FSharp.Collections

--------------------
type List<'T> =
  | ( [] )
  | ( :: ) of Head: 'T * Tail: 'T list
  interface IEnumerable
  interface IEnumerable<'T>
  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
union case Option.None: Option<'T>
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<_>
module Seq

from Microsoft.FSharp.Collections
val fold : folder:('State -> 'T -> 'State) -> state:'State -> source:seq<'T> -> 'State

Full name: Microsoft.FSharp.Collections.Seq.fold

Computation expressions in context

FP User Group + Craft Conf - April 2016

Andrea Magnorsky

@SilverSpoon

roundcrisis.com

wd

Computation Expressions

1: 
2: 
3: 
4: 
5: 
6: 
7: 
let getHtml(url:string) =  
  let req = WebRequest.Create url
  let response = req.GetResponse()
  use streatm = response.GetResponseStream()
  use reader = new StreamReader(streatm)

  reader.ReadToEnd().Length
1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
let getHtmlA(url:string) =  
  async{
      let req = WebRequest.Create url
      let! response = req.AsyncGetResponse() // ding!
      use streatm = response.GetResponseStream()
      use reader = new StreamReader(streatm)
      return reader.ReadToEndAsync().Length // ding!
      }
1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
let getHtmlA(url:string) =  
  //async{
      let req = WebRequest.Create url
      let (*! *) response = req.AsyncGetResponse() 
      use streatm = response.GetResponseStream()
      use reader = new StreamReader(streatm)
      (*return *) reader.ReadToEndAsync().Length 
  //    }
1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
let maybe = new MaybeBuilder()
let addNUmbers  =
    maybe {
        let x = 12
        let! y = Some 11
        let! z = Some 30
        return x + y + z
    }

builder

type SimplestBuilder () =

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
  member this.Bind(x,f) = 
    printfn "Bind begin  %A %s " (DateTime.Now.TimeOfDay)  (x.ToString()) 
    let y = f x
    printfn "Bind end  %A %s " (DateTime.Now.TimeOfDay)  (x.ToString()) 
    y
  member this.Return(x) = 
      printfn "Return %A %s"  (DateTime.Now.TimeOfDay) (x.ToString())
      x

async

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
9: 
open System

let sleepWorkflow  = async{
    printfn "Starting at %O" DateTime.Now.TimeOfDay
    do! Async.Sleep 2000
    printfn "Finished at %O" DateTime.Now.TimeOfDay
    }

Async.RunSynchronously sleepWorkflow      

mbrace

1: 
2: 
3: 
4: 
5: 
let job =
    cloud {
        return sprintf
        "run on worker '%s' " Environment.MachineName }
    |> runtime.CreateProcess
 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
let makeJob i =
    cloud {
        if i % 8 = 0 then failwith "fail"
        let primes = Sieve.getPrimes 1000000
        return sprintf
        "calculated %d primes %A on machine '%s'"
            primes.Length
            primes
            Environment.MachineName
    }

let jobs2 =  
    [ for i in 1 .. 10 ->
         makeJob i |> cluster.CreateProcess ]

example source

Notions of computation and monads (1991)

Moggi

Comprehending Monads (1990)

Monads for functional programming (1995)

wadler

Some not-useful-right-away info

  • There is a strong link between monads and category theory
  • Monads have 3 monadic laws that every monad must satisfy:
    • Left identity
    • Right identity and
    • Associativity

Monads eh?

meh

Monoids

Monoids

  • Closures \(a' \rightarrow a' \rightarrow a'\) (example int -> int -> int )
  • Identity \(x + I = x\)
  • Associativity \(x + (y + z) = (x + y ) + z\)
1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
type Colour = { r: byte; g: byte; b: byte; a: byte }

let addTwo c1 c2 = {
    r = c1.r + c2.r
    g = c1.g + c2.g
    b = c1.b + c2.b
    a = c1.a + c2.a
}
1: 
2: 
3: 
type Monoid<'a> =
    { neutral : 'a
      op : 'a -> 'a -> 'a }
1: 
2: 
3: 
4: 
5: 
6: 
let black = { r = 0uy; g = 0uy; b = 0uy; a = 0uy }

let colourAdd : Monoid<Colour> = {
    neutral = black
    op = (addTwo)
}
1: 
2: 
3: 
4: 
5: 
let c1 = { black with g = 254uy }
let c2 = { black with r = 254uy }

let l = [ c1; c2; black ]
        |> List.reduce (addTwo)
 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
type T = Colour

let M = colourAdd
let Z = M.neutral
let (++) = M.op

[<Property>]
let `` Z is the neutral element`` (v : T) =
    Z ++ v = v && v ++ Z = v

[<Property>]
let ``The op is associative`` (a : T, b : T, c : T) =
    a ++ (b ++ c) = (a ++ b ++ c)

fixer

A monad is a monoid in the category of endofunctors.

A monad is like a burrito.

Think of monads just like you would think about Legos. legos

scared-otter

Terror

Errors

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
let division a b c d=
    match b with
    | 0 -> None
    | _ -> match c with
           | 0 -> None
           | _ -> match d with
                  | 0 -> None
                  | _ -> Some (((a/b)/c)/d)

1. Extract the core

1: 
2: 
3: 
4: 
 let divide a b =
    match b with
    | 0 -> None
    | _ -> Some (a/b )

2. Write the Builder

1: 
2: 
3: 
4: 
5: 
6: 
type MaybeBuilder() =
    member __.Bind(value, func) =
        match value with
        | Some value -> func value
        | None -> None
    member __.Return value = Some value

3. Profit

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
9: 
let maybe  = MaybeBuilder()

let divisionM a b c d=
    maybe{
        let! x = divide a b
        let! y = divide x c
        let! z = divide y d
        return z
    }
 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
[<Test>]
let ``monad laws``() =
    let ret (x: int) = choose.Return x
    let n = sprintf "Choice : monad %s"
    let inline (>>=) m f = choose.Bind(m,f)
    fsCheck "left identity" <|
        fun f a -> ret a >>= f = f a
    fsCheck "right identity" <|
        fun x -> x >>= ret = x
    fsCheck "associativity" <|
        fun f g v ->
            let a = (v >>= f) >>= g
            let b = v >>= (fun x -> f x >>= g)
            a = b

Why learn this?

Computation Expressions

Most monads are computation expressions, not all computation expressions are monads

let, for and try .. with, but with a different semantics

Monoids again

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
9: 
  type Colour = { r : byte; g : byte; b : byte; a : byte }

  let addColour c1 c2 = 
      { r = c1.r + c2.r
        g = c1.g + c2.g
        b = c1.b + c2.b
        a = c1.a + c2.a }

  let neutral = { r = 0uy; g = 0uy; b = 0uy; a = 0uy }
1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
  type MonoidBuilder ()= 
    member this.Zero() = neutral
    member this.Combine(x, y) = addColour x  y    
    member x.For(sequence, f) =
        let combine a b = x.Combine(a, f b)
        let Z = x.Zero()
        Seq.fold combine Z sequence
    member x.Yield (a) = a
1: 
2: 
3: 
4: 
5: 
6: 
  let monoid = new MonoidBuilder()

  let monoidAdd xs= monoid {
       for x in xs do
         yield x
       }

Computation expressions or workflows

Computation expressions have been available in F# since 2007 and they are fully documented in the F# language specification

  • Abstract computations
  • Handling of effects

Maybe problems

  • Slow
  • Hard to debug
  • Operator overuse

otter

Next

rop

Thanks

@SilverSpoon

roundcrisis.com

Resources

Resources