unraveling the mystery of monads

57
Unraveling the Mystery of Monads Developing an intuitive understanding of monads (without resorting to Category Theory)

Upload: faisal-waris

Post on 10-May-2015

1.377 views

Category:

Technology


7 download

TRANSCRIPT

Page 1: Unraveling the mystery of monads

Unraveling the Mystery of Monads

Developing an intuitive understanding of monads(without resorting to Category Theory)

Page 2: Unraveling the mystery of monads

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

Page 3: Unraveling the mystery of monads

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

Page 4: Unraveling the mystery of monads

Monads: Motivating Example

• Imagine a set of AJAX calls with the shown dependency graph Get

EventsGet

Messages

UI Processing

Get Profile

user id

profile id, last login date profile id

profile, events, messages

parallel execution

Page 5: Unraveling the mystery of monads

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

$.ajax({ url: "messages?profile_id=" + profile.id + "&last_login=" + profile.last_login, type: 'POST', success: function (data, textStatus, jqXHR) { var messages = jQuery.parseJSON(jqXHR.responseText);

doUIProcessing(profile, events, messages);

}, error: function (data, textStatus, jqXHR) { notify(textStatus); } });

}, error: function (data, textStatus, jqXHR) { notify(textStatus); } }); }, error: function (data, textStatus, jqXHR) { notify(textStatus); }});

This is a serial version.

The parallel version was too daunting for me to even attempt!

Page 6: Unraveling the mystery of monads

F# + WebSharper - Async MonadParallel Version

async { try let! profile = getProfile userid

let! events,messages = getEvents profile.Id profile.LastLogin <||> getMessages profile.Id

doUIProcessing (profile, events, messages)

with | ex -> notify(ex.Message)}

Page 7: Unraveling the mystery of monads

Part I – Monad Basics

Page 8: Unraveling the mystery of monads

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?

Page 9: Unraveling the mystery of monads

Equivalent Models of Computation © 1940’s• Turing Machines• Developed by Alan Turing• Computing with machines

• Lambda Calculus• Alonzo Church• Computing with mathematics

The concept of algorithm was first introduced All function programming languages trace their roots to Lambda Calculus

There other models of computations such as Recursive

Functions, Relational, …

Page 10: Unraveling the mystery of monads

Lambda Calculus

• Lambda Calculus is very simple – there is only one thing called ‘lambda term’• Lambda Term

• Variable: x, a variable, is a lambda term• Lambda Abstraction: If t is a lambda term then λx.t is a lambda term

• Equivalent to defining a function• Application : if t and s are lambda terms then ts is a lambda term

• Equivalent to calling a function t with input value s

• Notes• A ‘variable’ is an identifier bound to the input value (not a memory slot)• There are no named functions• Functions only accept a single value but ‘currying’ is used for multiple input parameters• Functions are Higher Order, i.e. can accept other functions as input parameters and return

functions as values• Recursion is handled via fixed-point combinators such as the Y-combinator• Arguments are not evaluated before binding to lambda expression – lazy evaluation

Bottom Line:Any computable algorithm can be implemented using the simple definitions and rules of Lambda Calculus.

Your ‘program’ is a single lambda expression –

composed of other terms. Reducing the lambda term is

equivalent running the program

Page 11: Unraveling the mystery of monads

Function Composition The Essence of ‘Functional’ Programming

• A key to understanding monads• For the OO people among us

• Your program is essentially one large function composed of smaller functions• Functional programming is based on Lambda Calculus

• We learned function composition in high school:• f (x) : int int• g (x) : int int

• (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.

There are no ‘statements’ that you

can sequence one after the other –

everything must be done via function

composition

Page 12: Unraveling the mystery of monads

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

Page 13: Unraveling the mystery of monads

Composition Example in F# - Word Count

open Systemopen System.IOlet 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

Page 14: Unraveling the mystery of monads

Word Count Output

("the", 34253); ("and", 21394); ("to", 16536); ("of", 14920); ("a", 10418); ("he", 9411); ("in", 8789); ("his", 7941); ("that", 7485); ("was", 7235); ("with", 5659); ("had", 5338); ("not", 4510); ("at", 4502); ("it", 4389); ("her", 4348); ("as", 3908); ("on", 3769); ("but", 3626); ("him", 3612); ("for", 3412); ("she", 3259); ("i", 3234); ("is", 3064); ("you", 2860); ("from", 2666); ("all", 2566); ("said", 2536); ("by", 2368); ("were", 2368); ("be", 2346); (""", 2281); ("they", 2066); ("who", 1941); ("have", 1937); ("what", 1937); ("which", 1927); ("one", 1908); ("this", 1886); ("prince", 1748); ("so", 1661); ("an", 1614); ("or", 1554); ("pierre", 1483);…

Page 15: Unraveling the mystery of monads

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• UI• State• Exceptions• Continuations (asynchronous computations)• …

Its really about controlling or managing side effects

“… being explicit about side effects” – Erik Meijer

(Not OO-style rampant mutation)

Page 16: Unraveling the mystery of monads

Eugenio Moggi

• Eugenio Moggi is a professor of Computer Science at the University of Genoa, Italy.• He first described the general use of

monads (from Category Theory) to structure programs for side effects• Moggi’s work was about understanding

computation semantics to prove equivalence of programs (© 1991)• “Notions of Computation and Monads”,

Information and Computation (‘93)

Page 17: Unraveling the mystery of monads

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

Page 18: Unraveling the mystery of monads

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

Page 19: Unraveling the mystery of monads

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

Page 20: Unraveling the mystery of monads

Enter the Monad• What if you wrapped the input value into something

• Instead of just int you now have M int• 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• This opens up some possibilities• Because the type M is what you define• It is part of the monad implementation

• along with some functions which are described next

• However f, g & h take int as an input parameter not M int• The type signatures are not compatible• What to do?

• Well, managing all of this gets the ball rolling…

You need to implement the kind of monad you want

(or use an available implementation)

Don’t think of M as a Class. It could any type –

including a function type

Think of monad as a context around the data

that flows between functions

Page 21: Unraveling the mystery of monads

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

• Return – is a function that creates a monadic value from an ‘ordinary’ value

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

All three have to be consistent with

each other

Page 22: Unraveling the mystery of monads

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

Page 23: Unraveling the mystery of monads

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

Page 24: Unraveling the mystery of monads

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:

• Take out the ordinary value from the monadic value (1st argument: M ‘a)

• Invoke the function (2nd argument: a’ M ‘b)• Return the result (M’ b)

• The implementations of Return and Bind – corresponding to the monad – control:• how to package ordinary values into monadic values• How to extract ordinary value from monadic values

Return and Bind are invoked as flow

progresses through composed functions;

they provide the interjection points for

your code to do monad specific processing

Page 25: Unraveling the mystery of monads

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

Page 26: Unraveling the mystery of monads

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

Page 27: Unraveling the mystery of monads

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

Page 28: Unraveling the mystery of monads

Now An Example (finally!)

• Lets first define some functions…let f i = i * 4let g i = i + 2let 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

Page 29: Unraveling the mystery of monads

Count Monad

• A monad to count the number functions invoked during the evaluation of a computation

module CountMonad = type Count<'a> = 'a*int //pair of some type and an int

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 let output,_ = f input output, count + 1

let (>>=) = m_bind

The bind function is

assigned to an infix monadic bind operator

Note the monad implementation specifies the 3 requirements, Monadic Type,

Return & Bind

Page 30: Unraveling the mystery of monads

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

Page 31: Unraveling the mystery of monads

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

Page 32: Unraveling the mystery of monads

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

Page 33: Unraveling the mystery of monads

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

Page 34: Unraveling the mystery of monads

Count Monad: Function Modification

• Now we need to modify our functions slightly to work with the Count monad• Existing functions

let f i = i * 4let g i = i + 2let h i = i % 42

• Now we create monadic versions of our functions:let f' = f >> m_returnlet g' = g >> m_returnlet h' = h >> m_return

The monadic functions are created by composing our existing functions with the helper function.

The new functions have the type signature:int -> Count<int>

Page 35: Unraveling the mystery of monads

Count Monad: Composition

• Original compositionlet fgh = f >> g >> h

• The monadic versionlet fgh’ a = m_return a >>= f’ >>= g’ >>= h’

• We invoke it as follows…fgh' 24

• And get the result…val it : Count<int> = (14, 3)

The monadic version is not exactly the same as the ‘ordinary’ version

but feels very close.

Once the monad implementation is done and out the way, the code

flow feels very natural.

Page 36: Unraveling the mystery of monads

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

Page 37: Unraveling the mystery of monads

Trace Monad

• Instead of counting the number of function calls, we want to get a list of functions that were invoked

• Here is another monad implementation for the trace functionality

module TraceMonad = type Trace<'a> = 'a*(string list) 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

Page 38: Unraveling the mystery of monads

Using the Trace Monad

• Existing functionslet f i = i * 4let g i = i + 2let 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"let h' = h >> helper_return "h“

• The final monadic composition is the same as before:let fgh’ a = m_return a >>= f’ >>= g’ >>= h’fgh' 24Result: val it : int * string list = (14, ["f"; "g"; "h"])

We can swap the monad

implementations with very little change to our

application code

Page 39: Unraveling the mystery of monads

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

Page 40: Unraveling the mystery of monads

Part II – Monad Applications and Examples

Page 41: Unraveling the mystery of monads

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)

Page 42: Unraveling the mystery of monads

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)

Page 43: Unraveling the mystery of monads

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

Page 44: Unraveling the mystery of monads

Converting the Trace Monad to Enable Computation Expression Syntax

type TraceBuilder() = member x.Bind (comp, func) = m_bind comp func member x.Return (value) = m_return value

let trace = new TraceBuilder()----------------------------------------------------------------------let fgh2 a = trace { let! p1 = f' a let! p2 = g' p1 let! p3 = h' p2 return p3 }fgh2 24

The “m_bind” and “m_return” functions

are from the TraceMonad defined

earlier“let!” is the same as

the Bind operator and “return” is the

Return function

The compiler converts this syntax into the syntax we

used earlier

let fgh’ a = m_return a >>= f’ >>= g’ >>= h’

Page 45: Unraveling the mystery of monads

Utility of Computation Expression Syntax

compExp1 { let! p1 = f' a let! p2 = g' p1 let! p3 = h' p1 p2 return p3}

compExp2 { try let! p1 = f' a let! p2 = g' p1 let! p3 = h' p3 return p3 with | ex -> return <default value> }

compExp3 { let! p1 = f' a if p1 > 10 then let! p2 = g' p1 let! p3 = h' p3 return p3 else return p1}

Intermix monad with regular codeUse prior results downstream Try-Catch / Try-Finally

The compiler still converts these to function compositionbut code is cleaner as we avoid writing nested lambda expressions

Page 46: Unraveling the mystery of monads

Traditional Asynchronous Computation Approaches – Assume Invocation of a Remote Service

Future• A call to an asynchronous

service returns immediately with a Future object. The Future will eventually contain the response from the call. The calling thread can poll the Future and proceed further when the response is available.

Callback• A call to an asynchronous service is made with an

extra parameter – a callback• The way a callback is supplied is implementation

specific; it can be a:• lambda expression• a method name• an event handler• or a ‘closure’ in the form of an inline interface

implementation (such as Runnable in Java).

• The calling thread usually completes without waiting for a response. When the response arrives, the callback method is invoked and further processing is handled in the callback, typically on a different thread.

Page 47: Unraveling the mystery of monads

Sequencing Async. Calls

• Assume 3 synchronous service calls with sequential dependencylet 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

Page 48: Unraveling the mystery of monads

Sequencing Async. Calls: Issue Nested LambdasService1(

fun s1 ->Service2(s1,

fun s2 ->Service3(s1,s2,

fun s3 -> … <handle final result>…)))

Page 49: Unraveling the mystery of monads

Sequencing Async. Calls: F# Async Monadasync {

let! s1 = Service1Async()let! s2 = Service2Async(s1)let! s3 = Service3Async(s1, s2)return s3

} Callback for Service2(…) call

F# has utility methods to convert any .Net asynchronous

method to an Async monad: web service, database, HTTP,

TCP, etc.

Computation Expression allow asynchronous code to look like synchronous

code!

Page 50: Unraveling the mystery of monads

Parallel Async. Calls: Fork-Join

let AsyncHttp (url:string) = async {

// create the web request object let req = WebRequest.Create(url)

// get the response, asynchronously let! rsp = req.GetResponseAsync()

// read html stringuse stream = rsp.GetResponseStream()use reader = new System.IO.StreamReader(stream)return reader.ReadToEnd()

}

[ AsyncHttp "http://www.live.com" AsyncHttp "http://www.google.com" AsyncHttp "http://maps.live.com" AsyncHttp "http://maps.google.com" ] |> Async.Parallel|> Async.Run//returns a list of html strings

Source: Don Syme’s Blog

Page 51: Unraveling the mystery of monads

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

Page 52: Unraveling the mystery of monads

F# Type Providers & Query Computation Expression (LINQ)

type DB = SqlEntityConnection<ConnectionString=“ … database connection string … “>let context = EntityConnection.GetDataContext()

// join two tablesquery { for course in context.Courses do join dept in context.Departments on (course.DepartmentID = dept.DepartmentID) select (course, dept.Name) }

F# 3.0 enhancements allow custom

keywords (e.g. join, select) to be defined

for use in computation expressions

This computation expression uses .Net LINQ (Language Integrated Query) under-the-covers to generate and execute SQL on the database – this

expression is typed checked as normal F#

F# Type Providers extract and present type

information from remote sources (database, web

service, oData,…) at coding time

Page 53: Unraveling the mystery of monads

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

Page 54: Unraveling the mystery of monads

Insurance Policy Application UI(Data Collection Decision Tree)

Basic Applicant Info (name, age, …)

Home

Home Address + Value

Auto

Model, Miles Driven…

Life

Young Person

Physician Info

Older Person

Physician + Additional InfoAge affects Life Insurance data

collected

Page 55: Unraveling the mystery of monads

Insurance Policy Application UI Computation ExpressionFormlet.Do { let! applicant = ApplicantForm let! policy = policyForm let! insurance = match policy with | "h" -> HomeChoice | "a" -> AutoChoice | _ -> if applicant.Age < 50 then LifeYoungChoice else LifeOlderChoice return insurance }

All of the UI can be rendered on a single page which is

dynamically re-configured based on age and policy type

choices made by the user(see demo)

Monadic code is high level, very readable and

intention-preserving!

Page 56: Unraveling the mystery of monads

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

Page 57: Unraveling the mystery of monads

Q & A

Source: Aino Corry