g meredith scala

79
Monadic Design Patterns for the Web Session 1 Monday, October 17, 2011

Upload: sdeconf

Post on 07-May-2015

732 views

Category:

Technology


3 download

DESCRIPTION

Monadic Design Patterns for the Web

TRANSCRIPT

Page 1: G meredith scala

Monadic Design Patterns for the Web

Session 1

Monday, October 17, 2011

Page 2: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

Agenda

• What to expect

• Who is the audience

• Why monads

• The monadic toolbox

• A simple example

• Another simple example

Monday, October 17, 2011

Page 3: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

Agenda (cont)

• Hinting at a more complex example

• Where we might go from here

• Questions?

Monday, October 17, 2011

Page 4: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

What to expect

• Fun!

• Simplicity!

• Engagement!

• Ok... and some challenge

• Occasionally, people’s brains do melt out of their ears...

Monday, October 17, 2011

Page 5: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

What to expect

Browser

Container

Resource

Domain Logic

Service

Monday, October 17, 2011

Page 6: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

What to expect

Browser

Container

Resource

Domain Logic

Service

Monads for managing streams

Monday, October 17, 2011

Page 7: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

What to expect

Browser

Container

Resource

Domain Logic

Service

Monads for managing requests

Monads for managing streams

Monday, October 17, 2011

Page 8: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

What to expect

Browser

Container

Resource

Domain Logic

Service

Monads for managing requests

Monads for domain model

Monads for managing streams

Monday, October 17, 2011

Page 9: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

What to expect

Browser

Container

Resource

Domain Logic

Service

Monads for managing requests

Monads for domain model

Monads for managing streams

Monads for accessing store

Monday, October 17, 2011

Page 10: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

What to expect

Browser

Container

Resource

Domain Logic

Service

Parsing combinators

Algebraic data types

streams and continuations

LINQXQuery

SQL

Monday, October 17, 2011

Page 11: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

What to expect

• Monads provide a practical abstraction for everyday sorts of control flow and data structure in modern web app

• If objects were supposed to be the packaging of control and structure that provided optimal reuse, then monads seem to be a better object than object

Monday, October 17, 2011

Page 12: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

Who is the audience

• People who write code that serves a purpose

• Monads will feel natural to those with 2yrs functional programming

• Or, people who have 2yrs with distributed and network programming

• Nota bene: all code examples in Scala!

Monday, October 17, 2011

Page 13: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

Who is the audience

• But, really, monads are everywhere!

Monday, October 17, 2011

Page 14: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

Why monads

• To manage complexity

• Monads help your code scale

• Abstract structure and control

• Engage the compiler more

• Compositional

Monday, October 17, 2011

Page 15: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

The monadic toolbox

• What is a monad?

• Shape, wrap and roll, baby!

• Monads in a larger context

• Comprehensive comprehensions!

Monday, October 17, 2011

Page 16: G meredith scala

• Three key ingredients in a monad

• Shape

• wrap

• roll

Shapely monads

Monday, October 17, 2011

Page 17: G meredith scala

Embracing shape

“eh?”

“eh?”

“eh?”

“monads”

“eh?”

“monads,”wrap

roll

Shape

Monday, October 17, 2011

Page 18: G meredith scala

• Monads may be canonically thought of as a way to structure an interface to “colored” braces

• Shape -- the color of the braces

• wrap -- putting things between braces

• roll -- flattening nested braces (i.e. rolling them up)

Embracing shape

[ ]

[ ]“eh?”

[ ]“monads” [ ]“eh?”[ ]

“monads” “eh?”[ ],

Monday, October 17, 2011

Page 19: G meredith scala

Shape : <red> ... </red>

wrap : queen => <red>queen</red>

roll : <red><red>knight</red><red>queen</red></red>

=>

<red>knight queen</red>

Embracing shape

Monday, October 17, 2011

Page 20: G meredith scala

Shape : <list> ... </list>

wrap : queen => <list>queen</list>

roll : <list><list>knight</list><list>queen</list></list>

=>

<list>knight queen</list>

Data structures as “colored” braces

Monday, October 17, 2011

Page 21: G meredith scala

Shape : <set> ... </set>

wrap : queen => <set>queen</set>

roll : <set><set>knight</set><set>queen</set></set>

=>

<set>knight queen</set>

Data structures as “colored” braces

Monday, October 17, 2011

Page 22: G meredith scala

• List and Set are actually the same structure up to a certain point -- the difference can be captured by a set of equations that Sets obey and Lists don’t

• a + b = b + a

• a + a = a

• How do we relate these equations to Shape, wrap and roll?

Monads refactor container code

Monday, October 17, 2011

Page 23: G meredith scala

a + b could just as easily be written +( a, b )

which could just as easily be written <+> a b </+>

which could just as easily be written

roll( <+><+>a</+><+>b</+></+> )

which could just as easily be written

roll( <+> wrap( a ) wrap( b ) </+> )

or

roll( wrap( a ) + wrap( b ) )

Monads refactor container code

Monday, October 17, 2011

Page 24: G meredith scala

wrap( a ) + wrap( b )

in the case of both List and Set

as long as we have safely ‘wrapped’ everything, then ‘+’ is the natural polymorphic interpretation in the ‘container’

Set1 + Set2 := Set1 U Set2

List1 + List2 := List1 append List2

Monads refactor container code

Monday, October 17, 2011

Page 25: G meredith scala

Set1 U Set2 == Set2 U Set1 (not true of Lists)

Set1 U Set1 == Set1 (not true of Lists)

Monads refactor container code

Monday, October 17, 2011

Page 26: G meredith scala

wrap( a ) + wrap( b )

<set><set>a</set> <set>b</set></set>

if this is really Set then this has to be the same as

<set><set>b</set> <set>a</set></set>

aka

wrap( b ) + wrap( a )

Monads refactor container code

Monday, October 17, 2011

Page 27: G meredith scala

• So List and Set can actually be thought of as factored into two pieces of information

• ( M, equations )

where

• M is the colored brace structure (Shape-wrap-n-roll)

• the equations give additional constraints about how braces behave.

• Lists have no additional equations -- such structures are called free.

Monads refactor container code

Monday, October 17, 2011

Page 28: G meredith scala

Every monad can be seen as a version of a data structure that has a ‘+’ and a unit for the ‘+’, 1.

We’ve seen how the brace metaphor gives a simple model of how the extra structure of wrap and roll allow to extend

‘+’ over entities we put inside the monadic container

roll( wrap( a ) + wrap( b ) )

It also relates the unit, 1, of the ‘+’ to wrap (which is often called the unit of the monad)

Monads refactor container code

Monday, October 17, 2011

Page 29: G meredith scala

The unit of the ‘+’ has a canonical representation as the empty braces:

<red> </red>

roll( <red><red> </red> <red> queen </red></red> )

=

<red> queen </red>

=

roll( <red><red> queen </red><red> </red></red> )

Monads refactor container code

Monday, October 17, 2011

Page 30: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

A simple exampleclass MList[A]( elems : A* )

extends List[A]( elems ) {

def wrap ( a : A ) : MList[A] = {

new MList( a )

}

def roll ( mma : MList[MList[A]] ) : MList[A] = {

( Nil /: mma )( ( acc, ma ) => acc.append( ma ) )

}

}

Monday, October 17, 2011

Page 31: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

A simple example (cont)

• What can we say about this code?

• What about legacy uses of List?

• What about future uses of List?

Monday, October 17, 2011

Page 32: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

A simple example

trait Option[+A]

case class Some[+A]( a : A ) extends Option[A]

case object None extends Option[Nothing]

for( Some( a ) <- optA ) yield { f( a ) }

Monday, October 17, 2011

Page 33: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

Another simple example

trait LeftRightTree[A]

case class Leaf[A]( a : A )

extends LeftRightTree[A]

case class Branch[A](

left : List[LeftRightTree[A]],

right : List[LeftRightTree[A]]

) extends LeftRightTree[A]

Monday, October 17, 2011

Page 34: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

Another simple example (cont)

• We have a choice when we implement unit

def wrap( a : A ) : LeftRightTree[A] = {

Branch( List( a ), Nil )

}

or

def wrap( a : A ) : LeftRightTree[A] = {

Branch( Nil, List( a ) )

}

Monday, October 17, 2011

Page 35: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimiliarity LLC

The Monadic API as a View

trait Monad[M[_]] {

def unit [A] ( a : A ) : M[A]

def bind [A,B] ( ma : M[A], fn : A => M[B] ) : M[B]

}

shape

wrap

jelly roll

if you google for Shape, wrap and roll, you’ll only find my

presentations; if you use unit/yield/return and mult/bind,

you’ll find lots of hits

Monday, October 17, 2011

Page 36: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimiliarity LLC

A word about presentations

def bind [A,B] ( ma : M[A], f : A => M[B] ) : M[B] = {

mult( fmap( f )( ma ) )

}

def mult [A] ( mma : M[M[A]] ) : M[A] = {

bind[M[A],A]( mma, ( ma ) => ma )

}

def fmap [A,B] ( f : A => B ) : M[A] => M[B]

i confess! this is all a plot to expose you subliminally to

Category Theory

Monday, October 17, 2011

Page 37: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimiliarity LLC

The Monadic API as a View

class ListM[A] extends Monad[List] {

override def unit [S] ( s : S ) : List[S] = { List[S]( s ) }

override def bind [S,T] ( ls : List[S], fn : S => List[T] ) = {

( ( Nil : List[T] ) /: ls )( { ( acc, e ) => { acc ++ fn( e ) } } )

}

}

Monday, October 17, 2011

Page 38: G meredith scala

• Extensional

• We can explicitly give each element of the collection

• Intensional

• We must specify the elements programmatically -- such as by a rule

Two kinds of collections

Monday, October 17, 2011

Page 39: G meredith scala

Shape : <red> ... </red>

wrap : queen => <red>queen</red>

roll : <red><red>knight</red><red>queen</red></red>

=>

<red>knight queen</red>

Embracing shape

Monday, October 17, 2011

Page 40: G meredith scala

• Extensional -- examples

• { a, b, c }

• ( 1, 2, 3 )

• f(1) + g(2) + h(3)

• Intensional

• { a in Nat | a % 2 == 0 }

• fibs = 0 :: 1 :: zipWith (+) fibs (tail fibs)

• ∑ fi( i )

Two kinds of collections

Monday, October 17, 2011

Page 41: G meredith scala

• Infinite collections -- fibs, primes, etc, and also languages!

• Compressed collections -- individual elements are more easily computed than stored or otherwise expressed

• Collections calculated from data from the environment -- such as user input

Situations and intensions

Monday, October 17, 2011

Page 42: G meredith scala

• Infinite collections require some form of laziness or “just-in-time-ness” to avoid consuming all available memory

• Compressed collections can make use of laziness to avoid consuming compute cycles until it’s necessary

• Lazy also blurs the boundary between computing something just in time and waiting on i/o

Intensionally lazy

Monday, October 17, 2011

Page 43: G meredith scala

In the stream...

• More importantly the web 2.0 is teaching us that what initially looks like a small thing

type TwitterMsg = Char [140] // not legal Scala

becomes pretty valuable when it is iterated into a stream

abstract class TwitterStream

case class Twitterful( msg : TwitterMsg, strm : TwitterStream ) extends TwitterStream

Monday, October 17, 2011

Page 44: G meredith scala

{ pattern | generator1, ..., generatorM, condition1, ..., conditionN }

≈for( generator1; ...; generatorM; condition1;...; conditionN )

yield { pattern }

≈SELECT pattern FROM generator1, ..., generatorN

WHERE condition1, ..., conditionN

Intensions and comprehensions

Monday, October 17, 2011

Page 45: G meredith scala

Consider Set[A]

{ a, b, c, ... }

the language of extensional collections comes from the constructors of the type, A, we said we’d put in the collection, together with the Set operators

{ pattern | generator1, ..., generatorM, condition1, ..., conditionN }

where does the language of patterns and conditions come from?

Intensions and comprehensions

Monday, October 17, 2011

Page 46: G meredith scala

If monads are like containers, where’s the “take something out of the container interface”?

Intensions and comprehensions

Monday, October 17, 2011

Page 47: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimiliarity LLC

The Monadic API as a View

trait Monad[M[_]] {

def unit [A] ( a : A ) : M[A]

def bind [A,B] ( ma : M[A], fn : A => M[B] ) : M[B]

}

shape

wrap

jelly roll

Monday, October 17, 2011

Page 48: G meredith scala

Q: When can you check an element out of a monad?

A: With map you can check out (anything) any time you want, but you can never leave!

f : A => B

M[f] : M[A] => M[B]

Intensions and the Ruby Slippers

Monday, October 17, 2011

Page 49: G meredith scala

def transformResults(

normalizeResults : A => B

) : Option[B] = {

val intermediateRslts : Option[A] = getRawResults( ... )

for( rslt <- intermediateRslts ) yield {

normalizeResults( rslt )

}

}

Intensions and the Ruby Slippers

Monday, October 17, 2011

Page 50: G meredith scala

for( ptn <- src ; if condition ) yield { e( ptn ) }

≈src.map(

p => p match {

case ptn => if condition { e( ptn ) }

case _ => throw new Exception( “” )

}

)

Intensions and comprehensions

Monday, October 17, 2011

Page 51: G meredith scala

for( ptn <- src ; if condition ) yield { e( ptn ) }

≈src.map(

p => p match {

case ptn => if condition { e( ptn ) }

case _ => throw new Exception( “” )

}

)

Intensions and comprehensionsSELECT pattern FROM generator1, ..., generatorN

WHERE condition1, ..., conditionN

Monday, October 17, 2011

Page 52: G meredith scala

for( ptn <- src ; if condition ) yield { e( ptn ) }

≈src.map(

p => p match {

case ptn => if condition { e( ptn ) }

case _ => throw new Exception( “” )

}

)

Intensions and comprehensionsSELECT pattern FROM generator1, ..., generatorN

WHERE condition1, ..., conditionN

{ pattern | generator1, ..., generatorM, condition1, ..., conditionN }

Monday, October 17, 2011

Page 53: G meredith scala

Comprehension syntax

for( x <- expr1 ; y <- expr2 ; <stmts> ) yield expr3 = expr1 flatMap(

x => for( y <- expr2; <stmts> ) yield expr3

)

for( x<-expr1 ; y = expr2 ;<stmts> ) yield expr3 =

for(

( x, y ) <-

for( x <- expr1 ) yield ( x , expr2 ); <stmts>

) yield expr3

for( x <- expr1 if pred ) yield expr2 =

expr1 filter(x => pred) map (x => expr2 )

Monday, October 17, 2011

Page 54: G meredith scala

• Stuff goes in but never comes out -- the IO-monad

• Stuff goes in and sometimes comes out -- nearly all standard collections

• Every thing that goes in is matched by something coming out -- linearly typed collections

Notice that these correspond to transactional modes!

Three kinds of monad?

Monday, October 17, 2011

Page 55: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

Towards a more complex example

• Parsing

• Moral: the dog doesn’t bark

• Evaluation

• Moral: the dog barks quietly -- even in a distributed setting

• Storage?

Monday, October 17, 2011

Page 56: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

REPLs and Web Apps and DSLs, oh my!

Browser

Container

Resource

Domain Logic

Service

Monday, October 17, 2011

Page 57: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

REPLs and Web Apps and DSLs, oh my!

Browser

Container

Resource

Domain Logic

Service

Non-blocking continuation-based request handling

Monday, October 17, 2011

Page 58: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

REPLs and Web Apps and DSLs, oh my!

Browser

Container

Resource

Domain Logic

Service

User actions become expressions

in a DSL

Non-blocking continuation-based request handling

Monday, October 17, 2011

Page 59: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

REPLs and Web Apps and DSLs, oh my!

Browser

Container

Resource

Domain Logic

Service

User actions become expressions

in a DSL

Domain model = abstract syntax of

DSL

Non-blocking continuation-based request handling

Monday, October 17, 2011

Page 60: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

REPLs and Web Apps and DSLs, oh my!

Browser

Container

Resource

Domain Logic

Service

User actions become expressions

in a DSL

Domain model = abstract syntax of

DSL

Non-blocking continuation-based request handling

Evaluation as a service

Monday, October 17, 2011

Page 61: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

Parsing - compositional at multiple levels

Expressions in a DSL Parser

Syntax tree

Monday, October 17, 2011

Page 62: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

ParsingConcrete syntax

Normalization

Abstract syntax

Monday, October 17, 2011

Page 63: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

ParsingAbstract syntax

Evaluation

Domain value

Monday, October 17, 2011

Page 64: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

Parsing (DSLs)

• The surface API for parsing doesn’t (have to) change

• Grammars are already compositional: grammars are algebras!

• The programmatic API changes: parser combinators

Monday, October 17, 2011

Page 65: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

Parsing (DSLs)

• Internal vs External

• Parsing combinators vs higher level abstraction

• Domain requirements

Monday, October 17, 2011

Page 66: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

Internal vs External DSLs

• External

• independent, self-contained language with own grammar and semantics

• Example: SQL is a DSL for accessing relational storage

Monday, October 17, 2011

Page 67: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

Internal vs External DSLs

• Internal

• embedded or hosted DSL

• makes use of expressions and computations in ambient language

• examples

• lex/yacc -- semantic actions in C

• LINQ -- internal DSL for accessing storage

Monday, October 17, 2011

Page 68: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

Parsing combinators vs higher level abstraction

• Parsing combinators

• provide compositional mechanism

• work well in embedded situation

• BNF and other higher level abstractions

• considerably more concise

• target multiple platforms

Monday, October 17, 2011

Page 69: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

Example

term ::= symbol( term* ) | list | variable | ground

ground ::= strLit | numLit | boolLit

variable ::= uppercaseIdent

symbol ::= lowercaseIdent

Monday, October 17, 2011

Page 70: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

Exampleclass TermParser extends JavaTokenParsers {

def term : Parser[Any] =

application | list | ground | variable

def list : Parser[Any] =

"["~repsep( term, "," )~"]"

def ground : Parser[Any] =

stringLiteral | floatingPointNumber | "true" | "false"

def variable : Parser[Any] = ident

def application : Parser[Any] =

ident~"("~repsep( term, "," )~")"

}

Monday, October 17, 2011

Page 71: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

Domain requirements

• When DSL supports service-based/program-to-program computing

• language is “closed” -- no expression sublanguage

• When DSL supports human-interaction

• language is often “open” -- containing some expression sublanguage

Monday, October 17, 2011

Page 72: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

DSLs and algebras

• An algebra is a domain model (and don’t you forget it!)

• An algebra is the abstract syntax to the ...

• ... concrete syntax of a DSL

Monday, October 17, 2011

Page 73: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

Algebras

• Algebras and types are closely related

• Functional types are algebraic data types

• Understanding how these are related and languages for manipulating them will get you far

• Most importantly -- algebras are monads!

Monday, October 17, 2011

Page 74: G meredith scala

• List and Set are actually the same structure up to a certain point -- the difference can be captured by a set of equations that Sets obey and Lists don’t

• a + b = b + a

• a + a = a

• How do we relate these equations to Shape, wrap and roll?

Monads refactor container code

Remember this?

Monday, October 17, 2011

Page 75: G meredith scala

• So List and Set can actually be thought of as factored into two pieces of information

• ( M, equations )

where

• M is the colored brace structure (Shape-wrap-n-roll)

• the equations give additional constraints about how braces behave.

• Lists have no additional equations -- such structures are called free.

Monads refactor container code

And this?

Monday, October 17, 2011

Page 76: G meredith scala

Monads and algebras

• An algebra is expressed entirely as a set of generators

• ≈ constructors

• ≈ grammar

• and relations aka equations

• Generators and relations are 2/3’s of the specification of a DSL

Monday, October 17, 2011

Page 77: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

Where we might go from here

• We haven’t talked about control flow

• So, let’s talk a little about it...

Monday, October 17, 2011

Page 78: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

Why monads -- did we do what we promised?

• To manage complexity

• Monads help your code scale

• Abstract structure and control

• Engage the compiler more

• Compositional Actually... monads don’t necessarily

compose!

Monday, October 17, 2011

Page 79: G meredith scala

Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011

Questions?

Monday, October 17, 2011