scalaz by example (an io taster) -- pdxscala meetup jan 2014
DESCRIPTION
Slides from an informal talk I gave at PDX Scala last night on an often missed part of Scalaz: IO.TRANSCRIPT
Patterns vs Abstractions Code Motivating Examples Applications
SCALAZ BY EXAMPLE
Figure: Credit http://www.flickr.com/photos/slambo_42
Susan Potter @SusanPotterScalaPDX 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 find . -name "*.rb" \2 | xargs egrep "#.*?TODO:" \3 | 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 final case class Somefink[A](a: A) extendsPossiblyMaybe[A]
2 final case object Nowt extends PossiblyMaybe[Nothing]
3
4 sealed trait PossiblyMaybe[+A]5 object PossiblyMaybeOps {6 def noneDefault[A](pm: PossiblyMaybe[A])(a:
A): A = pm match {7 case Somefink(x) => x8 case _ => a9 }
10 }
Note _ in second match, caters for nulls with Java interop
9
Patterns vs Abstractions Code Motivating Examples Applications
START WITH "CLOSED" MODEL
1 final case object Production extends Env2 final case object Staging extends Env3 final case class QA(n: Int) extends Env4 final case class Dev(u: String) extends Env5 final case object Integration extends Env6 sealed trait Env7 object Env {8 /* companion object code... "instances" */9 }
10
Patterns vs Abstractions Code Motivating Examples Applications
EXTEND VIA ADHOC POLYMORPHISM
1 // companion object for Env2 object Env {3 // default "instances" over type Env4 // for typeclasses below5 implicit val EnvRead: Read[Env] = ???6 implicit val EnvShow: Show[Env] = ???7
8 // maybe you want ability to use9 // one of two implementations of Order[Env]
10 // as well as Equal[Env]. Anyone?11 implicit val EnvOrder: Order[Env] = ???12 implicit val EnvEqual: Equal[Env] = ???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 trait MyApp {4 def start(env: Env): IO[Unit]5 }6
7 def readConfig(env: Env):8 IO[BufferedSource] = ???9
10 def parseConfig(bs: BufferedSource):11 IO[Map[String, String]] = ???12
13 def setupMyApp(pool: ConnectionPool):14 IO[MyApp] = ???
14
Patterns vs Abstractions Code Motivating Examples Applications
IO: "CONSTRUCTION" (2/2)
1 def initialize(env: Env): IO[MyApp] = for {2 bs <- readConfig(env)3 map <- parseConfig(bs)4 app <- setupMyApp(pool)5 } yield app6
7 def withCookieSessions(app: MyApp):8 IO[MyApp] = ???9
10 def withServerSessions(app: MyApp):11 IO[MyApp] = ???12
13 def run(env: Env): IO[Unit] = for {14 app <- initialize(env)15 app2 <- withCookieSessions(app)16 } yield app2.start(env)
15
Patterns vs Abstractions Code Motivating Examples Applications
IO: ERROR HANDLING (1/2)
1 import scalaz._, Scalaz._, effect._2
3 def process(rq: Request):4 IO[Response] = ???5
6 def showErrorTrace:7 Throwable => IO[Response] = ???8
9 def logErrorTrace:10 Throwable => IO[Response] = ???11
12 def reportErrorTrace:13 Throwable => IO[Response] = ???
16
Patterns vs Abstractions Code Motivating Examples Applications
IO: ERROR HANDLING (2/2)
1 def handleReq(rq: Request)(implicit e: Env) =2 env match {3 case Production =>4 process(rq).except(logErrorTrace)5
6 case Staging =>7 process(rq).except(reportErrorTrace)8
9 case _ =>10 process(rq).except(showErrorTrace)11 }
17
Patterns vs Abstractions Code Motivating Examples Applications
IO: TESTING EXAMPLE
1 import scala.io.{BufferedSource , Codec}2 import scalaz._, Scalaz._, effect._3 import java.io.{ByteArrayInputStream => JBAIS
}4
5 implicit val codec = Codec("UTF-8")6 IO(new BufferedSource(new JBAIS("""{7 "host": "localhost",8 "port": "5432",9 "driver": "my.awesome.PostgresDriver",
10 "protocol": "postgres",11 "name": "contactsdb"12 }""".getBytes(codec.charSet))))
18
Patterns vs Abstractions Code Motivating Examples Applications
IO: TESTING EXAMPLE
1 // At the end of the universe we then do...2 run(env).unsafePerformIO3
4 // or whatever your starting point is, e.g.5 main(args).unsafePerformIO6
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 usedas:
→ 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: Effects, "linear happy path", and more
→ Applicatives: "validations", safer Java interop, and more
→ More: e.g. Arrows, Zippers, Lenses, Tagged Types, …
22
Patterns vs Abstractions Code Motivating Examples Applications
THINKING ALGEBRAICALLY
→ Properties: property based testing: quickcheck, scalacheck
→ Data Types: start closed, extend using "type classes",dependent types, etc when relevant
→ Abstractions: build small building blocks, use motar tobuild solid walls
→ Dist Systems: using algebraic abstractions, properties tobuild more useful distributed systems
23
Patterns vs Abstractions Code Motivating Examples Applications
QUESTIONS?
24