Upload
sdeconf
View
730
Download
3
Embed Size (px)
DESCRIPTION
Monadic Design Patterns for the Web
Citation preview
Monadic Design Patterns for the Web
Session 1
Monday, October 17, 2011
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
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
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
Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011
What to expect
Browser
Container
Resource
Domain Logic
Service
Monday, October 17, 2011
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
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
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
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
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
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
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
Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011
Who is the audience
• But, really, monads are everywhere!
Monday, October 17, 2011
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
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
• Three key ingredients in a monad
• Shape
• wrap
• roll
Shapely monads
Monday, October 17, 2011
Embracing shape
“eh?”
“eh?”
“eh?”
“monads”
“eh?”
“monads,”wrap
roll
Shape
Monday, October 17, 2011
• 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
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
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
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
• 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
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
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
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
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
• 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
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
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
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
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
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
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
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
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
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
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
• 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
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
• 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
• 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
• 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
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
{ 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
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
If monads are like containers, where’s the “take something out of the container interface”?
Intensions and comprehensions
Monday, October 17, 2011
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
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
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
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
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
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
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
• 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
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
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
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
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
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
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
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
Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011
ParsingConcrete syntax
Normalization
Abstract syntax
Monday, October 17, 2011
Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011
ParsingAbstract syntax
Evaluation
Domain value
Monday, October 17, 2011
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
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
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
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
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
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
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
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
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
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
• 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
• 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
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
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
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
Lucius Gregory Meredith, Managing Partner, Biosimilarity LLC -- SDEC 2011
Questions?
Monday, October 17, 2011