Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Scalaz 8: A Whole New Game

8,045 views

Published on

Scalaz 8 is the latest edition of the popular functional programming library for Scala. In this whirlwind tour, maintainer John A. De Goes discusses some of the hottest features of Scalaz 8, including all of the following:

* A fast, concurrent, and leak-free effect system, which has small, composable, and powerful primitives for building practical, real-world software;
* A non-linear type class hierarchy, which permits a more powerful hierarchy that infers well without devastating ambiguous implicit errors;
* A new encoding for abstractions in category theory that providers higher fidelity and enables new categories of useful software to be developed;
* A Scala 2.12 encoding of opaque types that powers improved performance and better developer UX.

In this tour, you’ll see how the design of Scalaz 8 was inspired by a desire to provide Scala developers with a principled, performant, and pragmatic library that never sacrifices the safety and equational reasoning properties of functional programming. You’ll see live code snippets that show you how solving complex real world problems is simpler, faster, safer, and more reasonable than in previous versions of Scalaz. And hopefully you’ll be inspired at just how far functional programming in Scala has come in the past decade.

Published in: Technology
  • i­f y­ou t­h­i­n­k T­h­e­l­m­A`s st­ory ­is ­n­e­At,, t­hr­e­e w­e­e­ks ­A­g­o ­my ­c­ous­i­n­ns st­e­p-­d­A­A­d ­g­ot $7275 just s­itt­i­n­g t­h­er­e ­e­l­ev­e­n ­h­ours ­A w­e­e­k ­fr­o­m t­h­er­e ­A­p­Art­m­e­nt ­A­n­d t­h­ey'r­e ­c­l­Ass­m­At­e's s­ist­er`s ­n­e­i­g­h­b­our ­d­i­d t­h­is ­f­or ­e­i­g­ht ­m­o­nt­hs ­A­n­d ­g­ot ­p­A­i­d ­ov­er $7275 ­p­Art t­i­m­e ­fr­o­m t­h­e­ir ­p­c. ­A­p­p­l­i­e t­h­e st­e­ps ­Av­A­i­l­A­b­l­e ­h­er­e,­ COPY AND PAST >>>> www.101pays.com
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • This are things I did not overlook while I was listing the things I wanted from a love spell in my relationship after breakup. 1) I requested that I get back my ex and our relationship last for the rest of our earthly lives. 2) I asked that the love spell should strengthen EACH of our abilities that we may utilize them in order to sustain our relationship which I so hope to become a marriage one day. 3) That we BOTH may resolve all conflicts with peaceful words, while remaining cognizant of one another’s feeling and come to a compromise when benefits all parties involved. 4) That whatever haunts HIM in his childhood, that he can let that go and he know that I hold none of that against him and I accept and love him for the person he is today. Through all of this with Dr. Wakina via dr.wakinalovetemple@gmail.com, we were worked on to be humble and accept accountability for our actions. I have apologized for my incompetent behaviors. on the other hand, I can count the amount of time HE has apologized to me. The love spell made us understand that relationship is not about a tit-for-tat affair. An equal relationship is what we have at the moment, HE holds himself to the same level of accountability where I am concerned after the graceful love spell from Dr. Wakina.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Not certain where to begin, I was overwhelmed lately trying to get out of a funk situation in a relationship. My fiancé was a whole other story. He was downright hurtful and ungrateful; his life and belongings were in shambles. He was someone addicted to drugs and women. He liked hiding behind excuses, giving me reasons to live a reckless life. But we share great bond, we can’t let go because we aren’t perfect after all. One thing we needed was someone or a spell doctor that will place himself in our spot to cure or tell us how easy it is to maintain or build a relationship surrounded by true love and healthy living. However, the reality of my story is that Dr. Wakina via (dr.wakinalovetemple@gmail.com) with a succeeding love spell made sure none of my pipe dreams at the expenses of a broken heart become reality.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Hello everyone, I must start by saying that I didn’t go into marriage with expectation that it will fail after 8 years. I and my spouse where not compassionate to ourselves. Trying to work out my marriage was self-defeating, we don’t really know why we no longer find ourselves attractive anymore. All we secretly thought was divorce, we couldn’t agree or communicate anymore, it was emotionally difficult moments when we face each other in the bedroom. I know that a phycologist might not be able to help me go through divorce because it has never worked for me. Divorcing could traumatize our kids, I can’t let them be emotionally crippled. I remember my grandmother once told me that not issues can be resolved physically, I should try solving some issues spiritually through a well-known spiritual doctor. I can provide evidence that my life and marriage got more better and interesting with so much love and fulfilled promises after Dr. Wakina lighted up our fire with a magnificent love spell with the aid of dr.wakinalovetemple@gmail.com. The spell work I never regarded rewrote my story. I’m touched beyond words, thanks Dr. Wakina.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Nice !! Download 100 % Free Ebooks, PPts, Study Notes, Novels, etc @ https://www.ThesisScientist.com
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Scalaz 8: A Whole New Game

  1. 1. 1 SCALAZ 8 A WHOLE NEW GAME flatMap(Oslo) 2018 By John A. De Goes — @jdegoes
  2. 2. 2 Dec 6 2008 May 10 2011 Jul 24 2012 First Commit Scalaz 6.0 Scalaz 7.0 S C A L A Z T I M E L I N E - F R O M 1 T O 8 Scalaz is closing in on its 10 year anniversary! SCALAZ 8 WHEN IT’S READY! (SOON) ...
  3. 3. 3 SCALAZ 8 CONTRIBUTORS A F E W O F T H E Tomas Mikula @tomas_mikula Alexander Konovalov Jean-Baptiste Giraudeau Tim Steinbach Aloïs Cochard @alexknvl @jbgi @Tim_Steinbach @aloiscochard Plus Vincent Marquez, Stephen Compall, Edmund Noble, Kenji Yoshida, Emily Pillmore, Jose Cardona, Dale Wijnand, Harrison Houghton, & others. And John!
  4. 4. 4 4 BIG DEALS TYPE CLASSES A new encoding of type classes CATEGORY THEORY More precise abstractions OPAQUE TYPES Power and performance EFFECTS Effects without compromises Let’s explore how Scalaz 8 is changing the game!
  5. 5. 5 TYPE CLASSES TYPE CLASS HIERARCHY TYPE CLASS ENCODING Monoid Semigroup TYPE CLASS HEAVEN
  6. 6. 6 trait Semigroup[A] { def append(l: => A, r: => A): A } object Semigroup { def apply[A](implicit S: Semigroup[A]) = S } implicit class SemigroupSyntax[A](l: A) { def <> (r: => A)(implicit S: Semigroup[A]): A = S.append(l, r) } trait Monoid[A] extends Semigroup[A] { def zero: A } object Monoid { def apply[A](implicit S: Monoid[A]) = S } TYPE CLASSES TYPE CLASS HIERARCHY TYPE CLASS ENCODING TYPE CLASS HEAVEN
  7. 7. 7 implicit val MonoidInt = new Monoid[Int] { def zero = 0 def append(l: => Int, r: => Int): Int = l + r } def twice[A: Monoid](a: A): A = a <> a twice(2) TYPE CLASSES TYPE CLASS HIERARCHY TYPE CLASS ENCODING TYPE CLASS HEAVEN
  8. 8. 8 Traversable Monad Functor TYPE CLASSES TYPE CLASS HIERARCHY TYPE CLASS ENCODING TYPE CLASS HELL
  9. 9. 9 trait Functor[F[_]] { ... } trait Monad[F[_]] extends Functor[F] { ... } trait Traversable[F[_]] extends Functor[F] { ... } TYPE CLASSES TYPE CLASS HIERARCHY TYPE CLASS ENCODING TYPE CLASS HELL
  10. 10. 10 implicit val ListTraversable = new Traversable[List] { ... } implicit val ListMonad = new Monad[List] { ... } def doStuff[F[_]: Traversable: Monad, A, B]( fa: F[A], f: A => F[B]): F[B] = { ... } // ERROR: Ambiguous implicit values for Functor[List] doStuff(1 :: 2 :: 3 :: Nil) TYPE CLASSES TYPE CLASS HIERARCHY TYPE CLASS ENCODING TYPE CLASS HELL
  11. 11. 11 Traversable Monad Functor TYPE CLASSES TYPE CLASS HIERARCHY TYPE CLASS ENCODING TYPE CLASS HEAVEN
  12. 12. 12 TYPE CLASSES TYPE CLASS HIERARCHY TYPE CLASS ENCODING TYPE CLASS HEAVEN sealed abstract class InstanceOfModule { type InstanceOf[T] <: T def instanceOf[T](t: T): InstanceOf[T] } object InstanceOfModule { val impl: InstanceOfModule = new InstanceOfModule { override type InstanceOf[T] = T override def instanceOf[T](t: T) = t } } type InstanceOf[T] = InstanceOfModule.impl.InstanceOf[T] @inline final def instanceOf[T](t: T): InstanceOf[T] = InstanceOfModule.impl.instanceOf(t)
  13. 13. 13 TYPE CLASSES TYPE CLASS HIERARCHY TYPE CLASS ENCODING TYPE CLASS HEAVEN trait FunctorClass[F[_]] { … } trait MonadClass[F[_]] extends FunctorClass[F] { … } trait TraversableClass[F[_]] extends FunctorClass[F] { … } trait BH0 extends BH1 { implicit def monadFunctor[M[_]](implicit M: Monad[M]): Functor[M] = instanceOf(M) } trait BH1 { implicit def traversableFunctor[T[_]]( implicit T: Traversable[T]): Functor[T] = instanceOf(T) } trait BaseTypeclasses { type Functor[F[_]] = InstanceOf[FunctorClass[F]] type Monad[M[_]] = InstanceOf[MonadClass[M]] type Traversable[T[_]] = InstanceOf[TraversableClass[T]] } trait Scalaz extends BH0 with BaseTypeclasses
  14. 14. 14 TYPE CLASSES TYPE CLASS HIERARCHY TYPE CLASS ENCODING TYPE CLASS HEAVEN implicit val ListTraversable: Traversable[List] = instanceOf(new TraversableClass[List] { ... }) implicit val ListMonad: Monad[List] = instanceOf(new MonadClass[List] { ... }) def doStuff[F[_]: Traversable: Monad, A, B]( fa: F[A], f: A => F[B]): F[B] = { ... } // YAY!!!! doStuff(1 :: 2 :: 3 :: Nil)
  15. 15. 15 4 BIG DEALS TYPE CLASSES A new encoding of type classes CATEGORY THEORY More precise abstractions OPAQUE TYPES Power and performance EFFECTS Effects without compromises Let’s explore how Scalaz 8 is changing the game!
  16. 16. 16 CATEGORY THEORY “FUNCTOR” FUNCTOR OPPORTUNITY COST // OK trait Functor[F[_]] extends Invariant[F] { def map[A, B](fa: F[A])(f: A => B): F[B] } // Better trait FunctorClass[F[_]] { def map[A, B](f: A => B): F[A] => F[B] }
  17. 17. 17 CATEGORY THEORY “FUNCTOR” FUNCTOR OPPORTUNITY COST
  18. 18. 18 CATEGORY THEORY “FUNCTOR” FUNCTOR OPPORTUNITY COST val request: Api[Int] = GET *> path("/employees/") *> contentType("application/json") *> queryInt("limit") val response: Api[Json] = contentType("application/json") *> content(JsonCodec) val listEmployees = serviceM(request, response) { limit => loadAllEmployees(limit).toJson } val docs: Markdown = document(listEmployees) val server: IO[Exception, Unit] = compileToServer(listEmployees) val remoteService: Int => IO[Exception, Json] = remotely(listEmployees)("localhost", 80)
  19. 19. 19 CATEGORY THEORY “FUNCTOR” FUNCTOR OPPORTUNITY COST val charP = char ^ subset(c => c >= 32 && c != '"' && c != '') | (text("") *> escapedP) val strP = (text(""") *> charP.many <* text(""")) ^ chars val jStrP = strP ^ str_ ^ fix val digitP = (char ^ subset(c => c >= '0' && c <= '9')).label("digit") val nonZeroP = (char ^ subset(c => c >= '1' && c <= '9')).label("non-zero digit") val numP = (pure(1) | text("-") ^ element(-1)) * (text("0") ^ element("0") | (nonZeroP * digitP.many) ^ cons ^ chars) * (text(".") *> digitP.many1 ^ chars).optional * ((text("e") | text("E")) *> (pure(1) | text("+") ^ element(1) | text("-") ^ element(-1)) * (digitP.many1 ^ chars)).optional
  20. 20. 20 CATEGORY THEORY FUNCTOR ENDOFUNCTOR IN SCALA OPPORTUNITY GAIN trait Semicategory[->[_, _]] { type Obj[A] def andThen[A: Obj, B: Obj, C: Obj] (ab: A -> B, bc: B -> C): A -> C } trait Category[->[_, _]] extends Semicategory[->] { def id[A: Obj]: A -> A } trait Functor[F[_]] { type FromObj[A] type ToObj[A] type FromCat[A, B] type ToCat[A, B] def obj[A : FromObj]: ToObj[F[A]] def map[A : FromObj, B : FromObj](f: FromCat[A, B]): ToCat[F[A], F[B]] }
  21. 21. 21 CATEGORY THEORY FUNCTOR ENDOFUNCTOR IN SCALA OPPORTUNITY GAIN trait Trivial[A] type Endofunctor[F[_]] = Functor[F] { type FromObj[A] = Trivial[A] type ToObj[A] = Trivial[A] type FromCat[A, B] = A => B type ToCat[A, B] = A => B }
  22. 22. 22 CATEGORY THEORY FUNCTOR ENDOFUNCTOR IN SCALA OPPORTUNITY GAIN scalaz-http scalaz-codec scalaz-parsers scalaz-rpc scalaz-analytics ...
  23. 23. 23 4 BIG DEALS TYPE CLASSES A new encoding of type classes CATEGORY THEORY More precise abstractions OPAQUE TYPES Power and performance EFFECTS Effects without compromises Let’s explore how Scalaz 8 is changing the game!
  24. 24. 24 OPAQUE TYPES INTRODUCTION - MAYBE FIX - RECURSION SCHEMES VOID sealed trait MaybeModule { type Maybe[A] object Just { def unapply[A](ma: Maybe[A]): Option[A] = toOption(ma) } object Empty { def unapply[A](ma: Maybe[A]): Boolean = toOption(ma).isEmpty } def empty[A]: Maybe[A] def just[A](a: A): Maybe[A] def maybe[A, B](n: B)(f: A => B): Maybe[A] => B def fromOption[A](oa: Option[A]): Maybe[A] def toOption[A](ma: Maybe[A]): Option[A] } private[scalaz] object MaybeImpl extends MaybeModule { ... } final val Maybe: MaybeModule = MaybeImpl type Maybe[A] = Maybe.Maybe[A] TYPE CLASS HIERARCHY LIST - VIA FIX
  25. 25. 25 OPAQUE TYPES INTRODUCTION - MAYBE FIX - RECURSION SCHEMES VOID sealed abstract class InstanceOfModule { type InstanceOf[T] <: T def instanceOf[T](t: T): InstanceOf[T] } object InstanceOfModule { val impl: InstanceOfModule = new InstanceOfModule { override type InstanceOf[T] = T override def instanceOf[T](t: T) = t } } type InstanceOf[T] = InstanceOfModule.impl.InstanceOf[T] @inline final def instanceOf[T](t: T): InstanceOf[T] = InstanceOfModule.impl.instanceOf(t) TYPE CLASS HIERARCHY LIST - VIA FIX
  26. 26. 26 OPAQUE TYPES INTRODUCTION - MAYBE FIX - RECURSION SCHEMES VOID trait FixModule { type Fix[F[_]] def fix[F[_]](f: F[data.Fix[F]]): Fix[F] def unfix[F[_]](f: Fix[F]): F[data.Fix[F]] } private[data] object FixImpl extends FixModule { type Fix[F[_]] = F[data.Fix[F]] def fix[F[_]](f: F[data.Fix[F]]): Fix[F] = f def unfix[F[_]](f: Fix[F]): F[data.Fix[F]] = f } TYPE CLASS HIERARCHY LIST - VIA FIX
  27. 27. 27 OPAQUE TYPES INTRODUCTION - MAYBE FIX - RECURSION SCHEMES VOID trait IListModule { type IList[A] def uncons[A](as: IList[A]): Maybe2[A, IList[A]] } private[data] object IListImpl extends IListModule { type IList[A] = Fix[Maybe2[A, ?]] def uncons[A](as: IList[A]): Maybe2[A, IList[A]] = Fix.unfix[Maybe2[A, ?]](as) } TYPE CLASS HIERARCHY LIST - VIA FIX
  28. 28. 28 OPAQUE TYPES INTRODUCTION - MAYBE FIX - RECURSION SCHEMES VOID trait VoidModule { type Void def absurd[A](v: Void): A } @silent private[data] object VoidImpl extends VoidModule { type Void = Nothing def absurd[A](v: Void): A = v } TYPE CLASS HIERARCHY LIST - VIA FIX
  29. 29. 29 4 BIG DEALS TYPE CLASSES A new encoding of type classes CATEGORY THEORY More precise abstractions OPAQUE TYPES Power and performance EFFECTS Effects without compromises Let’s explore how Scalaz 8 is changing the game!
  30. 30. 30 EFFECTS // Program #1 val f1 = Future(getProductCategories()) val f2 = Future(getSponsoredProducts()) for { categories <- f1 sponsored <- f2 response <- buildResults(categories, sponsored) } yield response // Program #2 for { categories <- Future(getProductCategories()) sponsored <- Future(getSponsoredProducts()) response <- buildResults(categories, sponsored) } yield response FUTURE ERROR HANDLING CONCURRENCY IO[E, A] RESOURCE SAFETY INTERRUPTION IOREF[A] IOQUEUE[A] EXAMPLE ≠
  31. 31. 31 EFFECTS // Program #1 val f1 = Future(getProductCategories()) val f2 = Future(getSponsoredProducts()) for { categories <- f1 sponsored <- f2 response <- buildResults(categories, sponsored) } yield response // Program #2 for { categories <- Future(getProductCategories()) sponsored <- Future(getSponsoredProducts()) response <- buildResults(categories, sponsored) } yield response FUTURE ERROR HANDLING CONCURRENCY IO[E, A] RESOURCE SAFETY INTERRUPTION IOREF[A] IOQUEUE[A] EXAMPLE ≠
  32. 32. 32 EFFECTS class Future[+T] { ... def flatMap[S](f: (T) ⇒ Future[S])(implicit executor: ExecutionContext): Future[S] = ??? ... } FUTURE ERROR HANDLING CONCURRENCY IO[E, A] RESOURCE SAFETY INTERRUPTION IOREF[A] IOQUEUE[A] EXAMPLEAccidental pooling
  33. 33. 33 EFFECTS class Future[+T] { ... def flatMap[S](f: (T) ⇒ Future[S])(implicit executor: ExecutionContext): Future[S] = ??? ... } FUTURE ERROR HANDLING CONCURRENCY IO[E, A] RESOURCE SAFETY INTERRUPTION IOREF[A] IOQUEUE[A] EXAMPLEAccidental pooling
  34. 34. 34 EFFECTS FUTURE ERROR HANDLING CONCURRENCY IO[E, A] RESOURCE SAFETY INTERRUPTION IOREF[A] IOQUEUE[A] EXAMPLE Future Fibonacci Benchmark http://github.com/scalaz/scalaz 115x FASTER!
  35. 35. 35 EFFECTS FUTURE ERROR HANDLING CONCURRENCY IO[E, A] RESOURCE SAFETY INTERRUPTION IOREF[A] IOQUEUE[A] EXAMPLE Future Fibonacci Benchmark http://github.com/scalaz/scalaz 115x FASTER!
  36. 36. 36 EFFECTS IO[E, A] FUTURE ERROR HANDLING CONCURRENCY IO[E, A] RESOURCE SAFETY INTERRUPTION IOREF[A] IOQUEUE[A] EXAMPLE An immutable value that describes an effectful (I/O) program that may run forever, terminate due to defect... ...“fail” with a value of type E... or synchronously / asynchronously compute a value of type A.
  37. 37. 37 EFFECTS FUTURE ERROR HANDLING CONCURRENCY IO[E, A] RESOURCE SAFETY INTERRUPTION IOREF[A] IOQUEUE[A] EXAMPLE IO.point : (=> A) => IO[E, A] Lifts a pure A value into an IO data structure. IO.fail : E => IO[E, A] Creates a value representing failure with an E. IO.terminate : Throwable => IO[E, A] Terminates the currently executing fiber with a non-recoverable error. IO.sync : (=> A) => IO[E, A] Captures a synchronous effect inside a pure data structure. IO.async : <asynchronous> Captures an asynchronous effect inside a pure data structure. io.attempt[E2]: IO[E2, E / A] Creates an error-free value by surfacing any error into E / A. io.map(f: A => B): IO[E, B] Maps one value into another by applying the function on A. io.flatMap(f: A => IO[E, B]): IO[E, B] Sequences one value into another whose construction depends on the first value.
  38. 38. 38 EFFECTS try { try { try throw new Exception("e1") finally throw new Exception("e2") } finally throw new Exception("e3") } catch { // WHICH ONE??? case e : Exception => println(e.toString()) } FUTURE ERROR HANDLING CONCURRENCY IO[E, A] RESOURCE SAFETY INTERRUPTION IOREF[A] IOQUEUE[A] EXAMPLE Two exceptions are swallowed!!!
  39. 39. 39 EFFECTS FUTURE ERROR HANDLING CONCURRENCY IO[E, A] RESOURCE SAFETY INTERRUPTION IOREF[A] IOQUEUE[A] EXAMPLE Defect: Throwable Non-Recoverable Error Error State: E Recoverable Error Recover with attempt : IO[E, A] => IO[Void, E / A] Unhandled E Pass to fiber supervisor: Throwable => IO[Void, Unit] Terminate fiber (“Let it Crash”) Interruption
  40. 40. 40 EFFECTS FUTURE ERROR HANDLING CONCURRENCY IO[E, A] RESOURCE SAFETY INTERRUPTION IOREF[A] IOQUEUE[A] EXAMPLE val result : IO[Void, String / A] = IO.fail(“e1”).ensuring( IO.terminate(new Error(“e2”)).ensuring( IO.terminate(new Error(“e3)).attempt result.flatMap(putStrLn(_)) // ???
  41. 41. 41 EFFECTS FUTURE ERROR HANDLING CONCURRENCY IO[E, A] RESOURCE SAFETY INTERRUPTION IOREF[A] IOQUEUE[A] EXAMPLE 1. Errors can be handled completely to yield infallible computations IO[Void, A] 2. There is no way to lose any error, whether recoverable or non-recoverable 3. Unlike other approaches, all functor laws are completely satisfied 4. There is no magical auto-catching or tangling of the E error channel to Throwable 5. There are no inconsistencies in the error model and it seamlessly integrates with typed error staes, interruptions, resource safety
  42. 42. 42 EFFECTS FUTURE ERROR HANDLING CONCURRENCY IO[E, A] RESOURCE SAFETY INTERRUPTION IOREF[A] IOQUEUE[A] EXAMPLE try { val file1 = openFile(“file.1”) try { val file2 = openFile(“file.2”) joinFiles(file1, file2) } finally file2.close() } finally file1.close()
  43. 43. 43 EFFECTS FUTURE ERROR HANDLING CONCURRENCY IO[E, A] RESOURCE SAFETY INTERRUPTION IOREF[A] IOQUEUE[A] EXAMPLE openFile(f1).bracket(_.close()) { file1 => openFile(f2).bracket(_.close()) { file2 => joinFile(file1, file2) } } Acquire Release Use
  44. 44. 44 EFFECTS FUTURE ERROR HANDLING CONCURRENCY IO[E, A] RESOURCE SAFETY INTERRUPTION IOREF[A] IOQUEUE[A] EXAMPLE // Fork/join: def concurrentFib(n: Int): IO[Void, BigInt] = if (n <= 1) IO.point[Void, BigInt](n) else for { f1 <- concurrentFib(n - 1).fork f2 <- concurrentFib(n - 2).fork v1 <- f1.join v2 <- f2.join } yield v1 + v2
  45. 45. 45 EFFECTS FUTURE ERROR HANDLING CONCURRENCY IO[E, A] RESOURCE SAFETY INTERRUPTION IOREF[A] IOQUEUE[A] EXAMPLE // Parallelism: val ioAB : IO[E, (A, B)] = ioA.par(ioB)
  46. 46. 46 EFFECTS FUTURE ERROR HANDLING CONCURRENCY IO[E, A] RESOURCE SAFETY INTERRUPTION IOREF[A] IOQUEUE[A] EXAMPLE // Race 2 or more actions: val rez = getUrl(“primary”) race ( getUrl(“backup”))
  47. 47. 47 EFFECTS FUTURE ERROR HANDLING CONCURRENCY IO[E, A] RESOURCE SAFETY INTERRUPTION IOREF[A] IOQUEUE[A] EXAMPLE object cats { def fib(n: Int): IO[BigInt] = if (n <= 1) IO(n) else fib(n - 1).flatMap { a => fib(n - 2).flatMap(b => IO(a + b)) } } object scalaz { def fib(n: Int): IO[Void, BigInt] = if (n <= 1) IO.point[Void, BigInt](n) else fib(n - 1).flatMap { a => fib(n - 2).flatMap(b => IO.point(a + b)) } } // Never finishes!!! cats.fib(Int.MaxValue).start(_.cancel) // Interrupts immediately with cleanup: scalaz.fib(Int.MaxValue).fork(_.interrupt(???))
  48. 48. 48 EFFECTS FUTURE ERROR HANDLING CONCURRENCY IO[E, A] RESOURCE SAFETY INTERRUPTION IOREF[A] IOQUEUE[A] EXAMPLE // Computes forever!!! cats.fib(Int.MaxValue). race(cats.fib(10)) // Computes quickly by // interrupting loser: scalaz.fib(Int.MaxValue). race(scalaz.fib(10))
  49. 49. 49 EFFECTS FUTURE ERROR HANDLING CONCURRENCY IO[E, A] RESOURCE SAFETY INTERRUPTION IOREF[A] IOQUEUE[A] EXAMPLE // Purely functional, concurrent `var` for { ref <- IORef(2) v <- ref.modify(_ + 3) _ <- putStrLn("Value = " + v.debug) } yield ()
  50. 50. 50 EFFECTS FUTURE ERROR HANDLING CONCURRENCY IO[E, A] RESOURCE SAFETY INTERRUPTION IOREF[A] IOQUEUE[A] EXAMPLE // Asynchronous, non-blocking queue: for { queue <- IOQueue.make[Int] fiber <- queue.take.fork _ <- queue.offer(3) v <- fiber.join } yield v
  51. 51. 51 EFFECTS FUTURE ERROR HANDLING CONCURRENCY IO[E, A] RESOURCE SAFETY INTERRUPTION IOREF[A] IOQUEUE[A] EXAMPLE type Actor[E, I, O] = I => IO[E, O] implicit class ActorSyntax[E, I, O](actor: Actor[E, I, O]) { def ! (i: I): IO[E, O] = actor(i) } val makeActor: IO[Void, Actor[Void, Int, Int]] = for { counter <- IORef(0) queue <- IOQueue.make[(Int, Promise[Void, Int])] worker <- queue.take.flatMap(t => counter.modify(_ + t._1).flatMap(t._2.complete)).forever.fork actor = (n: Int) => for { promise <- Promise.make[Void, Int] _ <- queue.offer((n, promise)) value <- promise.get } yield value } yield actor ... for { actor <- makeActor v <- actor ! 20 } yield v
  52. 52. 52 SCALAZ 8 IS COMING SOON! W E W A N T Y O U T O C O N T R I B U T E THANK YOU! Thanks to the organizers of flatMap, the sponsors, & attendees. Follow me @jdegoes Join Scalaz at gitter.im/scalaz/scalaz T H E E N D

×