Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Scalaz By Example

Scalaz By Example

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

Avatar for Susan Potter

Susan Potter

January 09, 2014
Tweet

More Decks by Susan Potter

Other Decks in Programming

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
  2. Patterns vs Abstractions Code Motivating Examples Applications OO PATTERNS VS

    FP ABSTRACTIONS → More (Subjective -> Objective) → More (Ambiguous -> Precise) → "Fluffy" Interfaces -> Generic Functions 3
  3. Patterns vs Abstractions Code Motivating Examples Applications WARNING → Abstract

    Algebra -> (Continuous, Infinite) → Real World -> usually (Discrete, Finite) 5
  4. 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
  5. Patterns vs Abstractions Code Motivating Examples Applications EXAMPLE FUNCTION COMPOSITION

    1 (length . mapToUpper . sanitize) input Value based, through functions 8
  6. 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
  7. 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
  8. 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
  9. 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
  10. 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
  11. 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
  12. 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
  13. 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
  14. 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
  15. 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
  16. 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
  17. 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
  18. 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