How to Troubleshoot Apps for the Modern Connected Worker
Unraveling the mystery of monads
1. Unraveling the Mystery of
Monads
Developing an intuitive understanding of monads
(without resorting to Category Theory)
2. About Me
• Faisal Waris
• IT Career started in the 90’s with Smalltalk
• A wide variety of experience in a host technologies
and industries
• Blog: http://fwaris.wordpress.com
• Currently consulting with a major auto manufacturer
in Michigan
• Working on emerging technologies research in Analytics
and BI
• Pursing Post Graduate Studies
3. Language Background
• Smalltalk (90’s) [also some C++]
• OO + Functional
• Dynamic Typing
• Meta-programming
• Refection
• Java, C# (2001-2010)
• Was never really satisfied (although C# has made big strides)
• Still missed Smalltalk
• F# (2010+)
• Seemed to hit the spot
• Succinct and expressive
• Almost all of the needed features ; Innovative new features such as Type Providers
• Statically Typed but with Type Inference feels like a Dynamically Typed language
• ‘Functional-first’
• Monads
4. Monads: Motivating Example
• Imagine a
user id
set of AJAX
calls with Get
profile id, Profile
the shown last login date
profile id
dependency
graph Get
parallel execution
Get
Events Messages
profile, events, messages
UI
Processing
5. JQuery Serial Version
$.ajax({
url: "profile/" + user_id,
type: 'POST',
success: function (data, textStatus, jqXHR) {
var profile = jQuery.parseJSON(jqXHR.responseText);
$.ajax({
url: "events/" + profile.id,
type: 'POST',
success: function (data, textStatus, jqXHR) {
var events = jQuery.parseJSON(jqXHR.responseText); This is a serial
$.ajax({
version.
url: "messages?profile_id=" + profile.id + "&last_login=" + profile.last_login,
type: 'POST',
success: function (data, textStatus, jqXHR) { The parallel version
var messages = jQuery.parseJSON(jqXHR.responseText);
was too daunting for
doUIProcessing(profile, events, messages);
me to even attempt!
},
error: function (data, textStatus, jqXHR) { notify(textStatus); }
});
},
error: function (data, textStatus, jqXHR) { notify(textStatus); }
});
},
error: function (data, textStatus, jqXHR) { notify(textStatus); }
});
8. How to Grok Monads
• First forget almost everything you know about ‘normal’ programming
• Forget
• Variables and Assignments
• Statements
• Loops
• …
• Now go back to the basics
• … the very basics
• What does it mean to compute?
10. Lambda Calculus
• Lambda Calculus is very simple – there is only one thing called ‘lambda term’
• Lambda Term Bottom Line:
• Variable: x, a variable, is a lambda term Any computable algorithm
• Lambda Abstraction: If t is a lambda term then λx.t is a lambda term can be implemented using
• Equivalent to defining a function the simple definitions and
• Application : if t and s are lambda terms then ts is a lambda term rules of Lambda Calculus.
• Equivalent to calling a function t with input value s
• Notes Your ‘program’ is a single
• A ‘variable’ is an identifier bound to the input value (not a memory slot) lambda expression –
• There are no named functions composed of other terms.
• Functions only accept a single value but ‘currying’ is used for multiple inputReducing the lambda term is
parameters
equivalent running the
• Functions are Higher Order, i.e. can accept other functions as input parameters and
return functions as values program
• Recursion is handled via fixed-point combinators such as the Y-combinator
• Arguments are not evaluated before binding to lambda expression – lazy evaluation
11. Function Composition
The Essence of ‘Functional’ Programming
• A key to understanding monads
• For the OO people among us
There are no
• Your program is essentially one large function composed of ‘statements’ that you
smaller functions
• Functional programming is based on Lambda Calculus can sequence one
after the other –
• We learned function composition in high school: everything must be
• f (x) : int int done via function
• g (x) : int int composition
• (f ∙ g) (x) : int int
• Equivalent to f (g (x))
• Think of (f ∙ g) as a new function built from the composition
of functions f and g.
12. Function Composition in Functional
Programming Languages
• In modern functional programming…
• One does not always get the sense that the entire program is one large
function
• However function composition is used very often
• Especially in Haskell
• Function Composition Operators
• Haskell: . (period)
• F#: >>
• F# has other ‘composition’ operators such as |> for pipelining
13. Composition Example in F# - Word Count
open System
open System.IO
let splitLine (l:string) = l.Split([|' '; '.'|], StringSplitOptions.RemoveEmptyEntries)
//string seq -> (string*int) seq
let wordCount =
Seq.map splitLine
>> Seq.collect (fun xs -> xs)
>> Seq.map (fun w -> w.ToLower())
>> Seq.countBy (fun w -> w)
>> Seq.sortBy (fun (_,c) -> -c)
let file = @"C:Users...SomeFile.txt"
file |> File.ReadLines |> wordCount
15. What About Side Effects?
• So far we have looked at pure functions – no side effects
• In the real world we need side effects
• otherwise the whole exercise does not seem very interesting
• How to combine pure functions with side effects?
• IO Its really about controlling
• UI or managing side effects
• State “… being explicit about
• Exceptions side effects” – Erik Meijer
• Continuations (asynchronous computations)
(Not OO-style rampant
• …
mutation)
17. Phillip Wadler
• Professor of Computer Science at University of Edinburgh
• First described the use of monads to structure functional
code – in the context of pure functional
languages, especially to manage side effects
• “Monads for Functional Programming” University of
Glasgow (‘92)
• Note
• Pure languages like Haskell need monads for IO and state
management
• Impure functional languages (Scala, F#, Clojure, etc.) don’t need
monads
• Monads are useful even in impure functional languages as a way
to structure code more cleanly
18. My Intuition about Monads
• Monads are a way of writing code at a higher level of abstraction
• In particular monads offer a clean way to managing ‘things on the side’
• So that your main code is free of clutter
• ‘things on the side’ is purposely left vague as it could be a vast variety of
things
• Examples later
• Seen in this way monads are like Aspect Oriented Programming (AOP)
• However AOP is uncontrolled
• You can’t reason about your program as you don’t know what is happening under the
covers
• Monads gives you similar benefit but in a precise and controlled way
• …explicit and part of the type system
19. Back to Function Composition
• Say you have a computation composed of three functions, f, g & h:
• (f ∙ g ∙ h) (x) : int int
• You want to manage ‘something on the side’
• Maybe you want to log something to the console each time a function is
called
• Or the functions need to access some global state - which may change as the
computation progresses
• And you don’t what the side activity to be too intrusive
• Well, with ‘normal’ function composition you can’t really do much
20. Enter the Monad
Don’t think of M as a Class.
• What if you wrapped the input value into something It could any type –
• Instead of just int you now have M int including a function type
• Read M int as Monad of int - a new type
• Your input is now a monadic value of type M int instead
of just a simple integer You need to
• This opens up some possibilities implement the kind
• Because the type M is what you define of monad you want
• It is part of the monad implementation
• along with some functions which are described next (or use an available
• However f, g & h take int as an input parameter not M implementation)
int
• The type signatures are not compatible Think of monad as a
• What to do? context around the data
• Well, managing all of this gets the ball rolling… that flows between
functions
21. Three Parts of Monad Implementation:
Monadic Type, Return & Bind
• Monadic Type –
• In typed functional languages it’s the type of the monadic value
• Note type does not mean Class, it could be a function type (there are other types)
• In dynamically typed languages such as Clojure this is usually a function
• Type: M All three have to be
• Return – is a function that creates a monadic value from an consistent with
‘ordinary’ value each other
• “return” is a cause of confusion because of its meaning in other languages
• Think of “…return me a monadic value”
• Also called “unit” in Haskell
• Type Signature: ’a M ‘a
• Bind – is a function that packages a monadic value with function
that accepts an ordinary value and produces another monadic
value
• Type Signature: M ’a (‘a M ‘b) M ‘b
22. Understanding the Bind Function
Signature
• Type Signature: M ’a (‘a M ‘b) M ‘b
• There are 3 terms:
Term Description
M ‘a Monadic value for an ordinary value of type ‘a
(‘a M ‘b) A function that takes an ordinary value of type ‘a and returns a
monadic value of type ‘b
M ‘b The return type of the bind function, Monadic value of type ‘b
• The bind function takes two parameters, M a’ & a function with signature (‘a
M ‘b) and returns M ‘b
23. A Bit About Currying / Partial Application
• let add x y = x + y
• A function that takes two numbers and returns their sum
• Now call this function as follows:
• let add7 = add 7
• Note that we have not supplied the 2nd parameter to add
• What is the value of add7?
• add7 is a new function that accepts a single number and returns 7 + the number
• The function add7 was created by partial application of add to 7
• Add and Add7 Function Signatures
• add: int int int
• add7: int int
24. Intuition about Return and Bind
• Return is easy – its just packaging an ordinary value
into a monadic value
• Bind [M ’a (‘a M ‘b) M ‘b ] works as follows:
Return and Bind are
• Take out the ordinary value from the monadic value (1st invoked as flow
argument: M ‘a) progresses through
• Invoke the function (2nd argument: a’ M ‘b) composed functions;
• Return the result (M’ b)
• The implementations of Return and Bind – they provide the
interjection points for
corresponding to the monad – control: your code to do monad
• how to package ordinary values into monadic values specific processing
• How to extract ordinary value from monadic values
25. Back Again to Function Composition
• Recall that we have a computation composed of three functions, f, g
& h:
• (f ∙ g ∙ h) (x) : int int
• Where each f, g & h have the signature int int
• Assume we have a monad implementation:
• Type: M ‘a
• Return: ‘a M ‘a
• Bind: M ‘a (‘a M ‘b) M ‘b
• Now we want to ‘monadify’ the computation
26. Modifying Functions to Work with
Monads
• To work with monads, we have to modify the function signatures of
f, g & h:
• From int int
• To int M int
• Where the generic type parameter ‘a is bound to int
• Let f’, g’, h’ be corresponding monadic functions with type signatures
• int M int
• Note that the new functions are not composable directly anymore
• The functions’ return type M int is not compatible with the input type int
27. Composing Monadic Functions
• The normal function bind operator does not apply with monadic
functions
• Recall that “ . “ is for Haskell and “ >> “ is the F# equivalent
• A new monadic bind infix operator is needed
• The monadic bind operator in Haskell is “ >>= “
• Given such an operator our new composed function is:
• let fgh’ a = (Return a) >>= f’ >>= g’ >>= h’)
28. Now An Example (finally!)
• Lets first define some functions…
let f i = i * 4
let g i = i + 2
let h i = i % 42
• And their composition…
let fgh = f >> g >> h
• And call the composed function…
fgh 24
• Which results in…
val it : int = 14
29. Count Monad
• A monad to count module CountMonad =
the number
functions invoked type Count<'a> = 'a*int //pair of some type and an int
during the
evaluation of a
computation let m_return (a:'a) : Count<'a> = a,0
let m_bind (c:Count<'a>) (f:'a->Count<'b>) : Count<'b>=
let input,count = c
The bind
function is let output,_ = f input Note the monad
implementation specifies the 3
assigned to an output, count + 1 requirements, Monadic
infix monadic
Type, Return & Bind
bind operator
let (>>=) = m_bind
30. Count Monad: Monad Type
• type Count<‘a> = ‘a*int
• The monadic value is a pair of the ‘ordinary’ value and an integer
• ‘a*int is the type signature for a 2-tuple, F# - e.g. (“a”, 1) : string * int
• In this case the ordinary value can be of any type, denoted by the
generic type parameter ‘a
• The integer part is the count that we want to maintain as we thread
the monad through the computation
31. Count Monad: Return Function
let m_return (a:'a) : Count<'a> = a,0
• The Return function simply converts an ordinary value to a monadic
value
• A pair or 2-tuple of the given value and an integer
• The initial count is set to 0
32. Count Monad: Bind Function
let m_bind (c:Count<'a>) (f:'a->Count<'b>) : Count<'b> =
let input,count = c
let output,_ = f input
output, count + 1
• The type signature is:
• Count<‘a> (‘a Count<‘b>) Count<‘b>
• As required for the bind function
• It is the heart of the monad:
• Receives a monad from the previous invocation
• It extracts the ordinary value and the count (let input, count = c)
• Invokes the bound function (f) with the extracted value (input) and gets a monad as a result
• It extract the ordinary value from the resulting monad (let output,_ = f input)
• Returns a new monad with the count incremented (output, count + 1)
• Each time the Bind function is invoked the count is incremented and passed along
33. Count Monad: Bind Operator
let (>>=) = m_bind
• The infix bind operator is technically not necessary because we can
use the Bind function
• However it is really desirable because the composed code looks much
cleaner
34. Count Monad: Function Modification
• Now we need to modify our functions slightly to work with the Count
monad
• Existing functions
let f i = i * 4
let g i = i + 2
let h i = i % 42
• Now we create monadic versions of our functions:
let f' = f >> m_return The monadic functions are created by composing
let g' = g >> m_return our existing functions with the helper function.
The new functions have the type signature:
let h' = h >> m_return int -> Count<int>
35. Count Monad: Composition
• Original composition
let fgh = f >> g >> h
• The monadic version
let fgh’ a = m_return a >>= f’ >>= g’ >>= h’
The monadic version is not exactly
• We invoke it as follows… the same as the ‘ordinary’ version
but feels very close.
fgh' 24
• And get the result… Once the monad implementation is
val it : Count<int> = (14, 3) done and out the way, the code
flow feels very natural.
36. Intuition about Monadic Bind
• Consider the monadic composition
• let fgh’ a = m_return a >>= f’ >>= g’ >>= h’
• By gluing the monadic functions together with the bind operator we
can insert our own logic between successive invocations of the
functions
• In this sense the “ >>= “ operator can be seen as a counterpart to the
semi-colon (“ ; “) statement delimiter in languages such as Java and
C#
• Hence we sometimes get a sense that implementing monads is like overriding
the semi-colon
37. Trace Monad
• Instead of counting the number of function module TraceMonad =
calls, we want to get a list of functions that were
invoked type Trace<'a> = 'a*(string list)
• Here is another monad implementation for the
trace functionality let m_return a = a,[]
let m_bind a f =
let input,l1 = a
let output,l2 = f input
output, l1 @ l2
let (>>=) = m_bind
38. Using the Trace Monad
• Existing functions
let f i = i * 4
let g i = i + 2
let h i = i % 42
• We define a different helper function to help ‘monadify’ our functions:
let helper_return fname (a:'a) = a,[fname]
• Now we create monadic versions of our functions:
let f' = f >> helper_return "f"
let g' = g >> helper_return "g" We can swap the
let h' = h >> helper_return "h“ monad
• The final monadic composition is the same as before: implementations
let fgh’ a = m_return a >>= f’ >>= g’ >>= h’ with very little
fgh' 24 change to our
Result: val it : int * string list = (14, ["f"; "g"; "h"]) application code
39. Monad Laws
• Monad implementations should obey these laws
• For proper function composition
//left unit
(m_return 0) >>= (fun b -> f' b) = f' 0
//right unit
(m_return 10) >>= (fun b -> m_return b) = (m_return 10)
//associative
(m_return 2000) >>= (fun a -> f' a >>= g') = ((m_return 2000 >>= f') >>= g')
41. Monads in Real Life
• Examples of monad use in the F# language
• Async monad
• Sequence Expressions
• Query Expressions
• Formlets monad - WebSharper and F#
• Haskell Monads
• IO
• State
• Reader / Writer
• List
• …
• (not elaborated in this presentation)
42. About F#
• F# is a hybrid functional – OO language for the .Net platform
• It was developed at Microsoft Research
• Principal designer: Don Syme
• It was most directly influenced by OCaml but also contains Haskell
influences
• Supports
• First class functions; pattern matching; type inference; meta-programming
(quotations); OO; actors; .Net integration; Computation Expressions (monads); Active
Patterns; Type Providers
• Available as part of Visual Studio (syntax highlighting, Intellisense, etc.)
• Mono versions of F# can run on Linux platforms (including Android)
43. F# Computation Expressions
• Like Haskell’s “ Do “ notation, F# provides an alternative syntax for
composing monadic computations
• The alternative syntax is easier to use in many scenarios
• The built-in monads in F# such as Async<‘a> use this syntax
• Computation Expressions have more than Bind and Return functions;
the also have
• Try-With / Try-Finally / While / For / Yield, …
• You have to implement a ‘builder’ type to enable this syntax in F#
code for a custom monad
44. Converting the Trace Monad to Enable
Computation Expression Syntax
The “m_bind” and
type TraceBuilder() =
“m_return” functions
member x.Bind (comp, func) = m_bind comp func
are from the
member x.Return (value) = m_return value
“let!” is the same as TraceMonad defined
the Bind operator earlier
let trace = new TraceBuilder()
and “return” is the ----------------------------------------------------------------------
Return function let fgh2 a =
trace {
The compiler let fgh’ a = m_return a >>= f’ >>= g’ >>= h’
let! p1 = f' a
converts this syntax let! p2 = g' p1
into the syntax we let! p3 = h' p2
used earlier return p3
}
fgh2 24
45. Utility of Computation Expression Syntax
Use prior results downstream Try-Catch / Try-Finally Intermix monad with regular code
compExp1 { compExp2 { compExp3 {
let! p1 = f' a try let! p1 = f' a
let! p2 = g' p1 let! p1 = f' a if p1 > 10 then
let! p3 = h' p1 p2 let! p2 = g' p1 let! p2 = g' p1
return p3 let! p3 = h' p3 let! p3 = h' p3
} return p3 return p3
with else
| ex -> return <default value> return p1
} }
The compiler still converts these to function composition
but code is cleaner as we avoid writing nested lambda expressions
46. Traditional Asynchronous Computation
Approaches – Assume Invocation of a
Remote Service
Future Callback
• A call to an asynchronous service is made
• A call to an asynchronous with an extra parameter – a callback
service returns immediately • The way a callback is supplied is
implementation specific; it can be a:
with a Future object. The Future • lambda expression
will eventually contain the • a method name
• an event handler
response from the call. The • or a ‘closure’ in the form of an inline interface
implementation (such as Runnable in Java).
calling thread can poll the
• The calling thread usually completes without
Future and proceed further waiting for a response. When the response
when the response is available. arrives, the callback method is invoked and
further processing is handled in the
callback, typically on a different thread.
47. Sequencing Async. Calls
• Assume 3 synchronous service calls with sequential dependency
let s1 = Service1 ()
let s2 = Service2 (s1)
let s3 = Service3 (s1,s2)
• Downstream service calls need results from previous calls
• Converting the service calls to asynchronous yields the following
method signatures:
Service1(callbackHandler<s1>)
Service2(s1, callbackHandler<s2>)
Service3(s1,s2,callbackHandler<s3>)
• The response is now returned in the callback handler which gets invoked on a
separate thread
48. Sequencing Async. Calls: Issue Nested
Lambdas
Service1(
fun s1 ->
Service2(s1,
fun s2 ->
Service3(s1,s2,
fun s3 -> … <handle final result>…)))
49. Sequencing Async. Calls: F# Async
Monad
async { F# has utility methods to
convert any .Net asynchronous
let! s1 = Service1Async() method to an Async monad:
let! s2 = Service2Async(s1) web
service, database, HTTP, TCP, e
let! s3 = Service3Async(s1, s2) tc.
return s3
} Callback for Computation Expression
Service2(…) call
allow asynchronous code
to look like synchronous
code!
50. Parallel Async. Calls: Fork-Join
[
AsyncHttp "http://www.live.com"
AsyncHttp "http://www.google.com"
AsyncHttp "http://maps.live.com" let AsyncHttp (url:string) =
async {
AsyncHttp "http://maps.google.com" // create the web request object
] let req = WebRequest.Create(url)
|> Async.Parallel
// get the response, asynchronously
|> Async.Run let! rsp = req.GetResponseAsync()
//returns a list of html strings
// read html string
use stream = rsp.GetResponseStream()
use reader = new System.IO.StreamReader(stream)
return reader.ReadToEnd()
Source: Don Syme’s Blog }
51. A Computation Expression for the
Fibonacci Sequence
let infinteFibonacci =
seq{ yield 0; yield 1
let rec fib n1 n2 = seq {yield n1+n2; yield! fib n2 (n1+n2)}
yield! fib 0 1}
//get the first 1000 Fibonacci values
infinteFibonacci |> Seq.take 1000
//0,1,1,2,3,5,8,…
Sequence Expressions “ seq { … } “ uses F# Computation Expression support
under the covers in a lazy evaluation style.
52. F# Type Providers & Query Computation
Expression (LINQ)
F# Type Providers extract
type DB = SqlEntityConnection<ConnectionString=“ … database connection string … “> and present type
let context = EntityConnection.GetDataContext() information from remote
sources (database, web
// join two tables
service, oData,…) at
query {
for course in context.Courses do coding time
join dept in context.Departments on (course.DepartmentID = dept.DepartmentID)
select (course, dept.Name)
}
F# 3.0 enhancements
allow custom
This computation expression uses .Net LINQ
keywords (e.g.
(Language Integrated Query) under-the-covers to
join, select) to be
generate and execute SQL on the database – this
defined for use in
expression is typed checked as normal F#
computation
expressions
53. Dynamic User Interfaces: WebSharper™
• By ‘dynamic’ we mean that the user interface re-configures itself
based on the choices made by the user (example next)
• About WebSharper
• F# and Visual Studio Extension for building Rich Web / Mobile Applications
• Integrates with many JavaScript Frameworks
• JQuery, JQueryMobile, SenchaTouch, etc.
• Combinators for HTML / HTML5
• Translates F# code to JavaScript
• Including Async computation expressions
• Leverages built-in F# meta-programming
• Uses Computation Expressions for Dynamic UI
54. Insurance Policy Application UI
(Data Collection Decision Tree)
Home Address +
Home
Value
Model, Miles
Basic Applicant
Driven…
Info Auto
(name, age, …)
Young Person Physician Info
Life
Age affects Life Physician +
Older Person
Insurance data Additional Info
collected
55. Insurance Policy Application UI
Computation Expression
Formlet.Do All of the UI can be rendered
on a single page which is
{
dynamically re-configured
let! applicant = ApplicantForm based on age and policy type
let! policy = policyForm choices made by the user
let! insurance = (see demo)
match policy with
| "h" -> HomeChoice
| "a" -> AutoChoice
| _ ->
if applicant.Age < 50 then LifeYoungChoice Monadic code is high
else LifeOlderChoice level, very readable and
return insurance intention-preserving!
}
56. Monads Summary
• A construct for writing code at a higher level of abstraction
• Applies to functional programming because it uses function
composition
• All examples presented used monadic bind function composition
• Monads are required to enable side-effects in pure functional
languages; e.g. Haskell
• Monads are not required in ‘impure’ languages but can greatly
facilitate certain kinds of scenarios:
• Examples, asynchronous & parallel computations; sequence expressions;
query expressions; dynamic user interfaces