Susan Potter
January 09, 2014
50

# Scalaz By Example

Slides from an informal talk I gave at PDX Scala last night on an often missed part of Scalaz: IO.

January 09, 2014

## Transcript

1. ### 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

3. ### Patterns vs Abstractions Code Motivating Examples Applications OO PATTERNS VS

FP ABSTRACTIONS → More (Subjective -> Objective) → More (Ambiguous -> Precise) → "Fluffy" Interfaces -> Generic Functions 3

5. ### Patterns vs Abstractions Code Motivating Examples Applications WARNING → Abstract

Algebra -> (Continuous, Infinite) → Real World -> usually (Discrete, Finite) 5

7. ### 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
8. ### Patterns vs Abstractions Code Motivating Examples Applications EXAMPLE FUNCTION COMPOSITION

1 (length . mapToUpper . sanitize) input Value based, through functions 8
9. ### Patterns vs Abstractions Code Motivating Examples Applications VALUING VALUES IN

REAL WORLD 1 final case class Somefink[A](a: A) extends PossiblyMaybe[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) => x 8 case _ => a 9 } 10 } Note _ in second match, caters for nulls with Java interop 9
10. ### Patterns vs Abstractions Code Motivating Examples Applications START WITH "CLOSED"

MODEL 1 final case object Production extends Env 2 final case object Staging extends Env 3 final case class QA(n: Int) extends Env 4 final case class Dev(u: String) extends Env 5 final case object Integration extends Env 6 sealed trait Env 7 object Env { 8 /* companion object code... "instances" */ 9 } 10
11. ### Patterns vs Abstractions Code Motivating Examples Applications EXTEND VIA ADHOC

POLYMORPHISM 1 // companion object for Env 2 object Env { 3 // default "instances" over type Env 4 // for typeclasses below 5 implicit val EnvRead: Read[Env] = ??? 6 implicit val EnvShow: Show[Env] = ??? 7 8 // maybe you want ability to use 9 // 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

13. ### 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
14. ### 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
15. ### 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 app 6 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
16. ### 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
17. ### 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
18. ### 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
19. ### Patterns vs Abstractions Code Motivating Examples Applications IO: TESTING EXAMPLE

1 // At the end of the universe we then do... 2 run(env).unsafePerformIO 3 4 // or whatever your starting point is, e.g. 5 main(args).unsafePerformIO 6 7 // only ONCE... most of the time ;) 19
20. ### 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

22. ### 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
23. ### 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 to build solid walls → Dist Systems: using algebraic abstractions, properties to build more useful distributed systems 23