getting the mvvm kicked out of your f#'n monads
TRANSCRIPT
Getting the MVVM kicked out of your F#'n Monads
Richard MinerichF# MVP of the Year
Senior Researcher, Bayard Rock@Rickasaurus / [email protected]
Fill this space with whatever you want (graphic, logo, whatever)
Time Warp back to 6th Grade
1 + (2 + 3) = 6 and (1 + 2) + 3 = 6
and
1 * (2 * 3) = (1 * 2) * 3
What about functions?let addOne x = x + 1let addTwo x = x + 2let addThree x = x + 3
All are int -> int
let addSix x = addOne(addTwo(addThree(x)))
>> is like add for functionslet addOne x = x + 1let addTwo x = x + 2let addThree x = x + 3
All are int -> int
let addSix = addOne >> addTwo >> addThree
5 + 0 = 5 and 3 * 1 = 3What would be the same thing for a function?
5 + 0 = 5 and 3 * 1 = 3What would be the same thing for a function?
let id f = fSo,
addFive >> id = addFive
functions are like numbersJust like (2 + 3) + 4 = 2 + (3 + 4)let addSix = (addOne >> addTwo) >> addThreeis the same aslet addSix = addOne >> (addTwo >> addThree)
Just like 6 = 0 + 6addSix = id >> addSix
(2 / 3) / 4 isn’t 2 / (3 / 4) but, let divByTwo x = x / 2let divByThree x = x / 3let divByFour x = x / 4
let divByTwentyFour = (divByTwo >> divByThree) >> divByFouris the same aslet divByTwentyFour = divByTwo >> (divByThree >> divByFour)
Why?
(1 - 2) - 3 isn’t 1 - (2 - 3) but,let minusOne x = x - 1let minusTwo x = x - 2let minusThree x = x - 3
let minusSix = (minusOne >> minusTwo) >> minusThreeis the same aslet minusSix = minusOne >> (minusTwo >> minusThree)
Why?
(1 - 2) - 3 isn’t 1 - (2 - 3) cont.let minusSix = minusTwo >> minusThree >> minusOne
Works great. But consider..
let minusSix = timesTwo >> divTwo >> minusThree >> minusThree
let ohNo = minusThree >> divTwo >> minusThree >> timesTwo
School’s out!
First class functions are in!
One Style of Abstractionlet ten = [1; 2; 3; 4] |> List.fold (fun x y -> x + y) 0let ten = [1; 2; 3; 4] |> List.reduce (fun x y -> x + y)let ten = [1; 2; 3; 4] |> List.reduce (+)let ten = [1; 2; 3; 4] |> List.sum
Fold – You provide the identityReduce – No identity neededReduce – Actually, just the operator is goodSum – Complete package, you provide nothing
It works with functions too!let ten =
[addOne; addTwo; addThree; addFour] |> List.fold (fun x f -> f x) 0
let ten = [addOne; addTwo; addThree; addFour]|> List.reduce (>>) <| 0
But how do we abstract ideas like these over the inside of functions?
Computation Expressions
Will Blow Your Mind
Computation Expressions!
-> Each line is a lambda.
-> In normal class methods you dispatch on type, with computation expressions you dispatch on language constructs.
What can you manipulate?Binding, Yielding and ReturningFor and WhileUse, Try-With and Try-FinallyPer-functionThe Entire Computation
The computation can be manipulated at all of these levels.
Let’s take a look at a simple CEtype MultBuilder () =
member t.Combine (x,y) = x * y member t.Yield (x) = x member x.Delay(f) = f()
let mult = new MultBuilder()mult {yield 2; yield 3}
It goes much deeper.Return – Stuff something in a containerBind – Pull it out
(or decide what to do it’s empty)
Computation expressions allow us to do this behind the scenes in an elegant way.
Optiontype Option<'a> = | Some of 'a | None
Most easily used as:
match x with| Some x -> x| None -> raise “Oh god, what now!”
But we can do better.
MaybeMaybe allows us to short circuit when
something goes wrong, instead of matching again and again.
“F# 2.0 is a book that assumes you are a professional, and as such, does not waste your time with a lot of fluff.”
Check out F#!Blog: RichardMinerich.comTwitter: @RickasaurusF# Community News: FSharpCentral.com
And the NYC F# User Group:http://www.meetup.com/nyc-fsharpWe meet monthly right here!
We thank the following companies for their gracious sponsorship
Platinum Sponsor
Gold Sponsors
Silver Sponsors