Patterns vs Abstractions

Code

Motivating Examples

Applications

SCALAZ BY EXAMPLE

Figure:

Credit http://www.flickr.com/photos/slambo_42

Susan Potter @SusanPotter
ScalaPDX January 2014
https://github.com/mbbx6spp/funalgebra

1
PATTERNS VS ABSTRACTIONS
Patterns vs Abstractions

Code

Motivating Examples

Applications

OO PATTERNS VS FP ABSTRACTIONS

→

More (Subjective -> Objective)

→ More (Ambiguous -> Precise)
→ "Fluffy" Interfaces -> Generic Functions

3
Patterns vs Abstractions

Code

Motivating Examples

Applications

LAYING BRICKS

4
Patterns vs Abstractions

Code

Motivating Examples

Applications

WARNING

→

Abstract Algebra -> (Continuous, Infinite)

→ Real World -> usually (Discrete, Finite)

5
CODE
Patterns vs Abstractions

Code

Motivating Examples

Applications

EXAMPLE UNIX PIPE

1
2
3

find . -name "*. rb" 
| xargs egrep "#.*? TODO:" 
| wc -l
Character-based, through file descriptors

7
Patterns vs Abstractions

Code

Motivating Examples

Applications

EXAMPLE FUNCTION COMPOSITION

1

( length . mapToUpper . sanitize ) input
Value based, through functions

8
Patterns vs Abstractions

Code

Motivating Examples

Applications

VALUING VALUES IN REAL WORLD
1

2

final case class Somefink [A](a: A) extends
PossiblyMaybe [A]
final case object Nowt extends PossiblyMaybe [
Nothing ]

3
4
5
6

7
8
9
10

sealed trait PossiblyMaybe [+A]
object PossiblyMaybeOps {
def noneDefault [A]( pm: PossiblyMaybe [A])(a:
A): A = pm match {
case Somefink (x) => x
case _ => a
}
}
Note _ in second match, caters for nulls with Java interop
9
Patterns vs Abstractions

Code

Motivating Examples

Applications

START WITH "CLOSED" MODEL

1
2
3
4
5
6
7
8
9

final case object Production extends Env
final case object Staging extends Env
final case class QA(n: Int) extends Env
final case class Dev(u: String ) extends Env
final case object Integration extends Env
sealed trait Env
object Env {
/* companion object code ... " instances " */
}

10
Patterns vs Abstractions

Code

Motivating Examples

Applications

EXTEND VIA ADHOC POLYMORPHISM
1
2
3
4
5
6

// companion object for Env
object Env {
// default " instances " over type Env
// for typeclasses below
implicit val EnvRead : Read[Env] = ???
implicit val EnvShow : Show[Env] = ???

7

// maybe you want ability to use
// one of two implementations of Order [Env]
// as well as Equal [Env ]. Anyone ?
implicit val EnvOrder : Order [Env] = ???
implicit val EnvEqual : Equal [Env] = ???

8
9
10
11
12
13

}

11
MOTIVATING EXAMPLES
Patterns vs Abstractions

Code

Motivating Examples

Applications

WHY USE IO MONAD?

→

Construct I/O "programs" from parts

→ Control error handling at runtime
→ Much easier to test various scenarios
→ And more …

13
Patterns vs Abstractions

Code

Motivating Examples

Applications

IO: "CONSTRUCTION" (1/2)
1

import scalaz ._, Scalaz ._, effect ._

2
3
4
5

trait MyApp {
def start (env: Env): IO[Unit]
}

6
7
8

def readConfig (env: Env):
IO[ BufferedSource ] = ???

9
10
11

def parseConfig (bs: BufferedSource ):
IO[Map[String , String ]] = ???

12
13
14

def setupMyApp (pool: ConnectionPool ):
IO[MyApp ] = ???
14
Patterns vs Abstractions

Code

Motivating Examples

Applications

IO: "CONSTRUCTION" (2/2)
1
2
3
4
5

def initialize (env: Env): IO[ MyApp] = for {
bs
<- readConfig (env)
map
<- parseConfig (bs)
app
<- setupMyApp (pool)
} yield app

6
7
8

def withCookieSessions (app: MyApp ):
IO[MyApp] = ???

9
10
11

def withServerSessions (app: MyApp ):
IO[MyApp] = ???

12
13
14
15
16

def run(env: Env): IO[Unit] = for {
app
<- initialize (env)
app2 <- withCookieSessions (app)
} yield app2. start (env)
15
Patterns vs Abstractions

Code

Motivating Examples

Applications

IO: ERROR HANDLING (1/2)
1

import scalaz ._, Scalaz ._, effect ._

2
3
4

def process (rq: Request ):
IO[ Response ] = ???

5
6
7

def showErrorTrace :
Throwable => IO[ Response ] = ???

8
9
10

def logErrorTrace :
Throwable => IO[ Response ] = ???

11
12
13

def reportErrorTrace :
Throwable => IO[ Response ] = ???

16
Patterns vs Abstractions

Code

Motivating Examples

Applications

IO: ERROR HANDLING (2/2)

1
2
3
4

def handleReq (rq: Request )( implicit e: Env) =
env match {
case Production =>
process (rq). except ( logErrorTrace )

5

case Staging =>
process (rq). except ( reportErrorTrace )

6
7
8

case _ =>
process (rq). except ( showErrorTrace )

9
10
11

}

17
Patterns vs Abstractions

Code

Motivating Examples

Applications

IO: TESTING EXAMPLE
1
2
3

import scala .io .{ BufferedSource , Codec }
import scalaz ._, Scalaz ._, effect ._
import java.io.{ ByteArrayInputStream => JBAIS
}

4
5
6
7
8
9
10
11
12

implicit val codec = Codec ("UTF -8")
IO(new BufferedSource (new JBAIS ("""{
"host": " localhost ",
"port": "5432",
" driver ": "my. awesome . PostgresDriver ",
" protocol ": " postgres ",
"name": " contactsdb "
}""". getBytes (codec . charSet ))))

18
Patterns vs Abstractions

Code

Motivating Examples

Applications

IO: TESTING EXAMPLE

1
2

// At the end of the universe we then do ...
run(env). unsafePerformIO

3
4
5

// or whatever your starting point is , e.g.
main(args). unsafePerformIO

6
7

// only ONCE ... most of the time ;)

19
Patterns vs Abstractions

Code

Motivating Examples

Applications

SAME TYPE, MANY "INTERFACES"

A type defined as a Monad (think: (>>=)) can also be used
as:
→

A Functor (think: fmap)

→ An Applicative (think: <*>, pure)
→ And possibly others

though not necessarily

20
APPLICATIONS
Patterns vs Abstractions

Code

Motivating Examples

Applications

KNOWN USES

→

Monoids:

Accumulators are everywhere, almost

→

Functors:

Lots of uses with common and user defined types

→

Monads:

→

Applicatives:

→

More:

Effects, "linear happy path", and more
"validations", safer Java interop, and more

e.g. Arrows, Zippers, Lenses, Tagged Types, …

22
Patterns vs Abstractions

Code

Motivating Examples

Applications

THINKING ALGEBRAICALLY

→

Properties:

→

Data Types:

→

Abstractions:

property based testing: quickcheck, scalacheck

start closed, extend using "type classes",
dependent types, etc when relevant
build small building blocks, use motar to

build solid walls
→

Dist Systems:

using algebraic abstractions, properties to
build more useful distributed systems

23
Patterns vs Abstractions

Code

Motivating Examples

Applications

QUESTIONS?

24

Scalaz By Example (An IO Taster) -- PDXScala Meetup Jan 2014

  • 1.
    Patterns vs Abstractions Code MotivatingExamples Applications SCALAZ BY EXAMPLE Figure: Credit http://www.flickr.com/photos/slambo_42 Susan Potter @SusanPotter ScalaPDX January 2014 https://github.com/mbbx6spp/funalgebra 1
  • 2.
  • 3.
    Patterns vs Abstractions Code MotivatingExamples Applications OO PATTERNS VS FP ABSTRACTIONS → More (Subjective -> Objective) → More (Ambiguous -> Precise) → "Fluffy" Interfaces -> Generic Functions 3
  • 4.
    Patterns vs Abstractions Code MotivatingExamples Applications LAYING BRICKS 4
  • 5.
    Patterns vs Abstractions Code MotivatingExamples Applications WARNING → Abstract Algebra -> (Continuous, Infinite) → Real World -> usually (Discrete, Finite) 5
  • 6.
  • 7.
    Patterns vs Abstractions Code MotivatingExamples Applications EXAMPLE UNIX PIPE 1 2 3 find . -name "*. rb" | xargs egrep "#.*? TODO:" | wc -l Character-based, through file descriptors 7
  • 8.
    Patterns vs Abstractions Code MotivatingExamples Applications EXAMPLE FUNCTION COMPOSITION 1 ( length . mapToUpper . sanitize ) input Value based, through functions 8
  • 9.
    Patterns vs Abstractions Code MotivatingExamples Applications VALUING VALUES IN REAL WORLD 1 2 final case class Somefink [A](a: A) extends PossiblyMaybe [A] final case object Nowt extends PossiblyMaybe [ Nothing ] 3 4 5 6 7 8 9 10 sealed trait PossiblyMaybe [+A] object PossiblyMaybeOps { def noneDefault [A]( pm: PossiblyMaybe [A])(a: A): A = pm match { case Somefink (x) => x case _ => a } } Note _ in second match, caters for nulls with Java interop 9
  • 10.
    Patterns vs Abstractions Code MotivatingExamples Applications START WITH "CLOSED" MODEL 1 2 3 4 5 6 7 8 9 final case object Production extends Env final case object Staging extends Env final case class QA(n: Int) extends Env final case class Dev(u: String ) extends Env final case object Integration extends Env sealed trait Env object Env { /* companion object code ... " instances " */ } 10
  • 11.
    Patterns vs Abstractions Code MotivatingExamples Applications EXTEND VIA ADHOC POLYMORPHISM 1 2 3 4 5 6 // companion object for Env object Env { // default " instances " over type Env // for typeclasses below implicit val EnvRead : Read[Env] = ??? implicit val EnvShow : Show[Env] = ??? 7 // maybe you want ability to use // one of two implementations of Order [Env] // as well as Equal [Env ]. Anyone ? implicit val EnvOrder : Order [Env] = ??? implicit val EnvEqual : Equal [Env] = ??? 8 9 10 11 12 13 } 11
  • 12.
  • 13.
    Patterns vs Abstractions Code MotivatingExamples Applications WHY USE IO MONAD? → Construct I/O "programs" from parts → Control error handling at runtime → Much easier to test various scenarios → And more … 13
  • 14.
    Patterns vs Abstractions Code MotivatingExamples Applications IO: "CONSTRUCTION" (1/2) 1 import scalaz ._, Scalaz ._, effect ._ 2 3 4 5 trait MyApp { def start (env: Env): IO[Unit] } 6 7 8 def readConfig (env: Env): IO[ BufferedSource ] = ??? 9 10 11 def parseConfig (bs: BufferedSource ): IO[Map[String , String ]] = ??? 12 13 14 def setupMyApp (pool: ConnectionPool ): IO[MyApp ] = ??? 14
  • 15.
    Patterns vs Abstractions Code MotivatingExamples Applications IO: "CONSTRUCTION" (2/2) 1 2 3 4 5 def initialize (env: Env): IO[ MyApp] = for { bs <- readConfig (env) map <- parseConfig (bs) app <- setupMyApp (pool) } yield app 6 7 8 def withCookieSessions (app: MyApp ): IO[MyApp] = ??? 9 10 11 def withServerSessions (app: MyApp ): IO[MyApp] = ??? 12 13 14 15 16 def run(env: Env): IO[Unit] = for { app <- initialize (env) app2 <- withCookieSessions (app) } yield app2. start (env) 15
  • 16.
    Patterns vs Abstractions Code MotivatingExamples Applications IO: ERROR HANDLING (1/2) 1 import scalaz ._, Scalaz ._, effect ._ 2 3 4 def process (rq: Request ): IO[ Response ] = ??? 5 6 7 def showErrorTrace : Throwable => IO[ Response ] = ??? 8 9 10 def logErrorTrace : Throwable => IO[ Response ] = ??? 11 12 13 def reportErrorTrace : Throwable => IO[ Response ] = ??? 16
  • 17.
    Patterns vs Abstractions Code MotivatingExamples Applications IO: ERROR HANDLING (2/2) 1 2 3 4 def handleReq (rq: Request )( implicit e: Env) = env match { case Production => process (rq). except ( logErrorTrace ) 5 case Staging => process (rq). except ( reportErrorTrace ) 6 7 8 case _ => process (rq). except ( showErrorTrace ) 9 10 11 } 17
  • 18.
    Patterns vs Abstractions Code MotivatingExamples Applications IO: TESTING EXAMPLE 1 2 3 import scala .io .{ BufferedSource , Codec } import scalaz ._, Scalaz ._, effect ._ import java.io.{ ByteArrayInputStream => JBAIS } 4 5 6 7 8 9 10 11 12 implicit val codec = Codec ("UTF -8") IO(new BufferedSource (new JBAIS ("""{ "host": " localhost ", "port": "5432", " driver ": "my. awesome . PostgresDriver ", " protocol ": " postgres ", "name": " contactsdb " }""". getBytes (codec . charSet )))) 18
  • 19.
    Patterns vs Abstractions Code MotivatingExamples Applications IO: TESTING EXAMPLE 1 2 // At the end of the universe we then do ... run(env). unsafePerformIO 3 4 5 // or whatever your starting point is , e.g. main(args). unsafePerformIO 6 7 // only ONCE ... most of the time ;) 19
  • 20.
    Patterns vs Abstractions Code MotivatingExamples Applications SAME TYPE, MANY "INTERFACES" A type defined as a Monad (think: (>>=)) can also be used as: → A Functor (think: fmap) → An Applicative (think: <*>, pure) → And possibly others though not necessarily 20
  • 21.
  • 22.
    Patterns vs Abstractions Code MotivatingExamples Applications KNOWN USES → Monoids: Accumulators are everywhere, almost → Functors: Lots of uses with common and user defined types → Monads: → Applicatives: → More: Effects, "linear happy path", and more "validations", safer Java interop, and more e.g. Arrows, Zippers, Lenses, Tagged Types, … 22
  • 23.
    Patterns vs Abstractions Code MotivatingExamples Applications THINKING ALGEBRAICALLY → Properties: → Data Types: → Abstractions: property based testing: quickcheck, scalacheck start closed, extend using "type classes", dependent types, etc when relevant build small building blocks, use motar to build solid walls → Dist Systems: using algebraic abstractions, properties to build more useful distributed systems 23
  • 24.
    Patterns vs Abstractions Code MotivatingExamples Applications QUESTIONS? 24