Functional Error Handling with Cats

FUNCTIONALFUNCTIONAL
ERROR HANDLINGERROR HANDLING
WITH CATSWITH CATS
MARK CANLASMARK CANLAS ·· NE SCALA 2020NE SCALA 2020
Functional Error Handling with Cats
Functional Error Handling with Cats
Functional Error Handling with Cats
OPTIONOPTION[_][_]
TRYTRY[_][_]
EITHEREITHER[_, _][_, _]
FUNCTORFUNCTOR[_][_]
APPLICATIVEAPPLICATIVE[_][_]
MONADMONAD[_][_]
ERRORS ASERRORS AS DATADATA
Functional Error Handling with Cats
Functional Error Handling with Cats
PARSING STRINGSPARSING STRINGS
case class AncientRecord(
age: String,
name: String,
rateOfIncome: String
)
case class Citizen(
age: Int,
name: String,
rateOfIncome: Double
)
def parseRecord(rec: AncientRecord): Citizen
Functional Error Handling with Cats
PARSING FUNCTIONSPARSING FUNCTIONS
def parseAge(s: String)
def parseName(s: String)
def parseRate(s: String)
Functional Error Handling with Cats
AA =>  => FF[[BB]]
case class AncientRecord(
age: String,
name: String,
rateOfIncome: String
)
case class Citizen(
age: Int,
name: String,
rateOfIncome: Double
)
// fate of record not guaranteed, via F
def parseRecord(rec: AncientRecord): F[Citizen]
OptionOption[_][_]
def parseAge(s: String): Option[Int]
def parseName(s: String): Option[String]
def parseRate(s: String): Option[Double]
FOR COMPREHENSIONFOR COMPREHENSION
def parseRecord(rec: AncientRecord): Option[Citizen] =
for {
age <- parseAge(rec.age)
name <- parseName(rec.name)
rate <- parseRate(rec.rate)
} yield Citizen(age, name, rate)
PARSING WITH OPTIONPARSING WITH OPTION
def parseRecord(rec: AncientRecord): Option[Citizen] =
for {
age <- parseAge(rec.age) // Some[Int]
name <- parseName(rec.name) // Some[String]
rate <- parseRate(rec.rate) // Some[Double]
} yield
Citizen(age, name, rate) // Some[Citizen]
NOT ALL AVAILABLENOT ALL AVAILABLE
def parseRecord(rec: AncientRecord): Option[Citizen] =
for {
age <- parseAge(rec.age) // Some[Int]
name <- parseName(rec.name) // None
rate <- parseRate(rec.rate) // (does not run)
} yield
Citizen(age, name, rate) // None
FIRST ONE WINSFIRST ONE WINS
FIRST ERROR WINSFIRST ERROR WINS
Functional Error Handling with Cats
Functional Error Handling with Cats
Functional Error Handling with Cats
TryTry[_][_]
def parseAge(s: String): Try[Int]
def parseName(s: String): Try[String]
def parseRate(s: String): Try[Double]
PARSING WITH TRYPARSING WITH TRY
def parseRecord(rec: AncientRecord): Try[Citizen] =
for {
age <- parseAge(rec.age) // Success[Int]
name <- parseName(rec.name) // Failure[String]
rate <- parseRate(rec.rate) // (does not run)
} yield
Citizen(age, name, rate) // Failure[Citizen]
Functional Error Handling with Cats
Name Happy path Sad path
Option[_] Some[_] None
Try[_] Success[_] Failure[_]
Functional Error Handling with Cats
Functional Error Handling with Cats
ERROR ADTERROR ADT
sealed trait ParsingErr
case class UnreadableAge (s: String) extends ParsingErr
case class UnreadableName(s: String) extends ParsingErr
case class UnreadableRate(s: String) extends ParsingErr
Functional Error Handling with Cats
EitherEither[_, _][_, _]
def parseAge(s: String): Either[UnreadableAge, Int]
def parseName(s: String): Either[UnreadableName, String]
def parseRate(s: String): Either[UnreadableRate, Double]
PARSING WITH EITHERPARSING WITH EITHER
def parseRecord(rec: AncientRecord): Either[ParsingErr, Citizen] =
for {
age <- parseAge(rec.age) // Right[UnreadableAge, Int]
name <- parseName(rec.name) // Left[UnreadableName, String]
rate <- parseRate(rec.rate) // (does not run)
} yield
Citizen(age, name, rate) // Left[ParsingErr, Citizen]
Functional Error Handling with Cats
Name Happy path Sad path
Option[_] Some[_] None
Try[_] Success[_] Failure[_]
Either[E, _] Right[E, _] Left[E, _]
Functional Error Handling with Cats
def parseRecord(rec: AncientRecord): Either[ParsingErr, Citizen]
def parseRecord(rec: AncientRecord): Either[ParsingErr, Citizen]
sealed trait HttpResponse
case class HttpSucccess (s: String) extends HttpResponse
case class HttpClientError(s: String) extends HttpResponse
def present(res: Either[ParsingErr, Citizen]): HttpResponse
def parseRecord(rec: AncientRecord): Either[ParsingErr, Citizen]
sealed trait HttpResponse
case class HttpSucccess (s: String) extends HttpResponse
case class HttpClientError(s: String) extends HttpResponse
def present(res: Either[ParsingErr, Citizen]): HttpResponse
def httpError(err: ParsingError): HttpClientError
def httpSuccess(c: Citizen): HttpSucccess
USINGUSING .fold().fold()
val res: Either[ParsingErr, Citizen] = ???
val httpResponse: HttpResponse =
res
.fold(httpError, httpSuccess)
USINGUSING .leftMap().leftMap()
val res: Either[ParsingErr, Citizen] = ???
val httpResponse: HttpResponse =
res // Either[ParsingErr, Citizen]
.map(httpSuccess) // Either[ParsingErr, HttpSucccess]
.leftMap(httpError) // Either[HttpClientError, HttpSucccess]
.merge // HttpResponse
EitherEither[[EE, , AA]] BIFUNCTORBIFUNCTOR
Can map over E
Can map over A
POSTFIX SYNTAXPOSTFIX SYNTAX
import cats.implicits._
def luckyNumber: Either[String, Int] =
if (Random.nextBoolean)
42.asRight
else
"You are unlucky.".asLeft
Functional Error Handling with Cats
Functional Error Handling with Cats
IOIO[_][_]
def parseAge(s: String): IO[Int]
def parseName(s: String): IO[String]
def parseRate(s: String): IO[Double]
PARSING WITH IOPARSING WITH IO
def parseRecord(rec: AncientRecord): IO[Citizen] =
for {
age <- parseAge(rec.age) // successful
name <- parseName(rec.name) // error "raised"
rate <- parseRate(rec.rate) // (does not run)
} yield
Citizen(age, name, rate) // error raised in step 2
Name Happy path Sad path
Option[_] Some[_] None
Try[_] Success[_] Failure[_]
Either[E, _] Right[E, _] Left[E, _]
IO[_] IO[_] IO[_]
Functional Error Handling with Cats
MONAD TYPECLASSMONAD TYPECLASS
import cats._
import cats.effect._
import scala.util._
type EitherParsingErr[A] = Either[ParsingErr, A]
implicitly[Monad[Option]]
implicitly[Monad[Try]]
implicitly[Monad[EitherParsingErr]]
implicitly[Monad[IO]]
ERROR CHANNELSERROR CHANNELS
F[A] shape Payload Error channel
Try[A] A Throwable
IO[A] A Throwable
Either[E, A] A E
MONADERROR TYPECLASSMONADERROR TYPECLASS
import cats._
import cats.effect._
import scala.util._
type EitherParsingErr[A] = Either[ParsingErr, A]
implicitly[MonadError[Try, Throwable]]
implicitly[MonadError[IO, Throwable]]
implicitly[MonadError[EitherParsingErr, ParsingErr]]
TYPECLASS TABLETYPECLASS TABLE
Functor[_]  
Applicative[_]  
Monad[_] MonadError[_, _]
Functional Error Handling with Cats
Functional Error Handling with Cats
Functional Error Handling with Cats
PARSING WITH EITHERPARSING WITH EITHER
def parseRecord(rec: AncientRecord): Either[ParsingErr, Citizen] =
for {
age <- parseAge(rec.age) // Left[ParsingErr, Int]
name <- parseName(rec.name) // (does not run)
rate <- parseRate(rec.rate) // (does not run)
} yield
Citizen(age, name, rate) // only reports first error
GIVEN:GIVEN:
EitherEither[[EE, , AA]]
GIVEN:GIVEN:
EitherEither[[EE, , AA]]
WANT:WANT:
EitherEither[[ListList[[EE], ], AA]]
MONADS START WITH:MONADS START WITH:
EitherEither[[EE, , AA]]
MONADS START WITH:MONADS START WITH:
EitherEither[[EE, , AA]]
MONADS END WITH:MONADS END WITH:
EitherEither[[EE, , AA]]
Functional Error Handling with Cats
Functional Error Handling with Cats
ValidatedValidated[_, _][_, _]
ValidatedValidated[_, _][_, _]
def parseAge(s: String): Validated[UnreadableAge, Int]
def parseName(s: String): Validated[UnreadableName, String]
def parseRate(s: String): Validated[UnreadableRate, Double]
PARSING WITH VALIDATED???PARSING WITH VALIDATED???
def parseRecord(rec: AncientRecord): ???[Citizen] =
for {
age <- ??? // ???
name <- ??? // ???
rate <- ??? // ???
} yield
Citizen(age, name, rate) // ???
ACCUMULATIONACCUMULATION
def combine(
v1: Validated[ParsingErr, Int],
v2: Validated[ParsingErr, String]):
Validated[List[ParsingError], (Int, String)] =
(v1, v2) match {
case (Valid(n), Valid(s)) => Valid((n, s))
case (Invalid(err), Valid(s)) => Invalid(List(err))
case (Valid(n), Invalid(err)) => Invalid(List(err))
case (Invalid(e1), Invalid(e2)) => Invalid(List(e1, e2))
}
EitherEither[[EE, , AA]]
ValidatedValidated[[EE, , AA]]
VALIDATED AND EITHERVALIDATED AND EITHER
Used for capturing errors as data
"Exclusive disjunction"
(payload A or error E but never both)
Bifunctor over A and E
Name Happy path Sad path
Option[_] Some[_] None
Try[_] Success[_] Failure[_]
Either[E, _] Right[E, _] Left[E, _]
IO[_] IO[_] IO[_]
Validated[E, _] Valid[_] Invalid[E]
ERROR CHANNELSERROR CHANNELS
F[A] shape Payload Error channel
Try[A] A Throwable
IO[A] A Throwable
Either[E, A] A E
Validated[E, A] A E
APPLICATIVEERROR TYPECLASSAPPLICATIVEERROR TYPECLASS
import cats._
import cats.effect._
type EitherParsingErr[A] = Either[ParsingErr, A]
type ValidatedParsingErr[A] = Validated[ParsingErr, A]
implicitly[ApplicativeError[IO, Throwable]]
implicitly[ApplicativeError[EitherParsingErr, ParsingErr]]
implicitly[ApplicativeError[ValidatedParsingErr, ParsingErr]]
// does not compile
implicitly[MonadError[ValidatedParsingErr, ParsingErr]]
TYPECLASS TABLETYPECLASS TABLE
Functor[_]  
Applicative[_] ApplicativeError[_, _]
Monad[_] MonadError[_, _]
POSTFIX SYNTAXPOSTFIX SYNTAX
import cats.implicits._
def luckyNumber: Validated[String, Int] =
if (Random.nextBoolean)
42.valid
else
"You are unlucky.".invalid
Functional Error Handling with Cats
Functional Error Handling with Cats
ValidatedValidated[[EE, , AA]]
ValidatedValidated[[EE, , AA]]
ValidatedValidated[[EE, , AA]]
  
ValidatedValidated[[ListList[[EE], ], AA]]
EitherEither[[EE, , AA]]
EitherEither[[EE, , AA]]
EitherEither[[EE, , AA]]
  
EitherEither[[EE, , AA]]
ValidatedValidated[[ListList[[EE], ], AA]]
ValidatedValidated[[ListList[[EE], ], AA]]
ValidatedValidated[[ListList[[EE], ], AA]]
  
ValidatedValidated[[ListList[[EE], ], AA]]
ValidatedValidated[[ListList[_], _][_], _]
import cats.data._
def parseAge(s: String):
Validated[List[UnreadableAge], Int]
def parseName(s: String):
Validated[List[UnreadableName], String]
def parseRate(s: String):
Validated[List[UnreadableRate], Double]
ACCUMULATIONACCUMULATION
def combine(
v1: Validated[List[ParsingErr], Int],
v2: Validated[List[ParsingErr], String]):
Validated[List[ParsingError], (Int, String)] =
(v1, v2) match {
case (Valid(n), Valid(s)) => Valid((n, s))
case (Invalid(err), Valid(s)) => Invalid(err)
case (Valid(n), Invalid(err)) => Invalid(err)
case (Invalid(e1), Invalid(e2)) => Invalid(e1 ::: e2)
}
WITH SEMIGROUPWITH SEMIGROUP
def combine[F : Semigroup](
v1: Validated[F[ParsingErr], Int],
v2: Validated[F[ParsingErr], String]):
Validated[F[ParsingError], (Int, String)] =
(v1, v2) match {
case (Valid(n), Valid(s)) => Valid((n, s))
case (Invalid(err), Valid(s)) => Invalid(err)
case (Valid(n), Invalid(err)) => Invalid(err)
// powered by Semigroup[F]
case (Invalid(e1), Invalid(e2)) => Invalid(e1 |+| e2)
}
ValidatedValidated[[EE, , AA]]
ValidatedValidated[[FF[[EE], ], AA]]
FF :  : SemigroupSemigroup
TUPLE SYNTAXTUPLE SYNTAX
import cats._
import cats.data._
import cats.implicits._
val res: Validated[List[ParsingErr], Citizen] =
(
parseAge(rec.age),
parseName(rec.name),
parseRate(rec.rate)
)
.mapN(Citizen)
Functional Error Handling with Cats
USINGUSING .fold().fold()
val res: Validated[List[ParsingErr], Citizen] = ???
def httpErrors(errs: List[ParsingError]): HttpClientError
def httpSuccess(c: Citizen): HttpSucccess
val httpResponse: HttpResponse =
res
.fold(httpErrors, httpSuccess)
USINGUSING .leftMap().leftMap()
val res: Validated[List[ParsingErr], Citizen] = ???
def httpErrors(errs: List[ParsingError]): HttpClientError
def httpSuccess(c: Citizen): HttpSucccess
val httpResponse: HttpResponse =
res // Validated[List[ParsingErr], Citizen]
.map(httpSuccess) // Validated[List[ParsingErr], HttpSucccess]
.leftMap(httpErrors) // Validated[HttpClientError, HttpSucccess]
.merge // HttpResponse
Functional Error Handling with Cats
FIRST ERROR WINSFIRST ERROR WINS
ACCUMULATEDACCUMULATED
ERRORSERRORS
FIRST ERROR WINSFIRST ERROR WINS
FIRST ERROR WINSFIRST ERROR WINS
Modeling dependent validations
Unwrapping envelopes or decoding
FIRST ERROR WINSFIRST ERROR WINS
Modeling dependent validations
Unwrapping envelopes or decoding
Introducing gates/dependency onto independent
validations
Save on expensive computation
ACCUMULATED ERRORSACCUMULATED ERRORS
ACCUMULATED ERRORSACCUMULATED ERRORS
Modeling independent validations
Field-based structures (maps, records, objects)
ACCUMULATED ERRORSACCUMULATED ERRORS
Modeling independent validations
Field-based structures (maps, records, objects)
Minimize round-trips
ACCUMULATED ERRORSACCUMULATED ERRORS
Modeling independent validations
Field-based structures (maps, records, objects)
Minimize round-trips
Embracing parallelization
Functional Error Handling with Cats
Functional Error Handling with Cats
ListList[_][_]
import cats._
import cats.data._
import cats.implicits._
def parseAge(s: String):
Validated[List[UnreadableAge], Int]
def parseName(s: String):
Validated[List[UnreadableName], String]
def parseRate(s: String):
Validated[List[UnreadableRate], Double]
implicitly[Semigroup[List]]
NonEmptyListNonEmptyList[_][_]
import cats._
import cats.data._
import cats.implicits._
def parseAge(s: String):
Validated[NonEmptyList[UnreadableAge], Int]
def parseName(s: String):
Validated[NonEmptyList[UnreadableName], String]
def parseRate(s: String):
Validated[NonEmptyList[UnreadableRate], Double]
implicitly[Semigroup[NonEmptyList]]
POSTFIX SYNTAXPOSTFIX SYNTAX
import cats.data._
import cats.implicits._
def luckyNumber: Validated[NonEmptyList[String], Int] =
if (Random.nextBoolean)
42.validNel
else
"You are unlucky.".invalidNel
Functional Error Handling with Cats
APPENDINGAPPENDING
List(1, 2, 3) ++ List(4)
APPENDING FREQUENTLYAPPENDING FREQUENTLY
List(1, 2, 3) ++ List(4)
List(1, 2, 3, 4) ++ List(5)
List(1, 2, 3, 4, 5) ++ List(8, 9)
List(1, 2) ++ List(3, 4) ++ List(8, 9)
Functional Error Handling with Cats
LIST ACCUMULATIONLIST ACCUMULATION
// read from left to right
List(1, 2, 3, 4, 5) ++ List(8, 9)
LIST ACCUMULATION (A)LIST ACCUMULATION (A)
// via repeated traversals
List(1, 2, 3, 4, 5) ++ List(8, 9)
List(1, 2, 3, 4) ++ List(5, 8, 9)
List(1, 2, 3) ++ List(4, 5, 8, 9)
List(1, 2) ++ List(3, 4, 5, 8, 9)
List(1) ++ List(2, 3, 4, 5, 8, 9)
List(1, 2, 3, 4, 5, 8, 9)
LIST ACCUMULATION (B)LIST ACCUMULATION (B)
// via reverse list, built using fast prepend
List(1, 2, 3, 4) ++ ReverseList()
List(2, 3, 4) ++ ReverseList(1)
List(3, 4) ++ ReverseList(2, 1)
List(4) ++ ReverseList(3, 2, 1)
List() ++ ReverseList(4, 3, 2, 1)
SEQUENCESSEQUENCES
List(1, 2, 3, 4)
Seq(5)
Vector(6, 7, 8)
Nested(
List(9),
Array(10, 11, 12))
CHAINCHAINED TOGETHERED TOGETHER
Chain(
List(1, 2, 3, 4),
Seq(5),
Vector(6, 7, 8),
Chain(
List(9),
Array(10, 11, 12)))
ChainChain[_][_]
def parseAge(s: String):
Validated[Chain[UnreadableAge], Int]
def parseName(s: String):
Validated[Chain[UnreadableName], String]
def parseRate(s: String):
Validated[Chain[UnreadableRate], Double]
implicitly[Semigroup[Chain]]
NonEmptyChainNonEmptyChain[_][_]
def parseAge(s: String):
Validated[NonEmptyChain[UnreadableAge], Int]
def parseName(s: String):
Validated[NonEmptyChain[UnreadableName], String]
def parseRate(s: String):
Validated[NonEmptyChain[UnreadableRate], Double]
implicitly[Semigroup[NonEmptyChain]]
SEMIGROUPSEMIGROUP COLLECTIONSCOLLECTIONS
Name Provider Empty? Accumulation
performance
List Scala ✅ O(n^2)
NonEmptyList ❌ O(n^2)
Chain ✅ constant
NonEmptyChain ❌ constant
POSTFIX SYNTAXPOSTFIX SYNTAX
import cats.implicits._
def luckyNumber: Validated[NonEmptyChain[String], Int] =
if (Random.nextBoolean)
42.validNec
else
"You are unlucky.".invalidNec
Functional Error Handling with Cats
ALGEBRASALGEBRAS
trait ParserAlg[F[_]] {
def parseAge(s: String): F[Int]
def parseName(s: String): F[String]
def parseRate(s: String): F[Double]
}
TYPECLASS METHODSTYPECLASS METHODS
class BadParser[F[_]](implicit F: ApplicativeError[F, Throwable]) {
def parseAge(s: String): F[Int] =
// raised, not thrown
F.raiseError(new Exception("what a world"))
}
NESTEDNESTED FF ANDAND GG
trait FancyParserAlg[F[_], G[_]] {
def parseAge(s: String): F[G[Int]]
def parseName(s: String): F[G[String]]
def parseRate(s: String): F[G[Double]]
}
FF WITH TRANSFORMERWITH TRANSFORMER GTGT
trait FancyParserAlg[F[_]] {
def parseAge(s: String): GT[F, Int]
def parseName(s: String): GT[F, String]
def parseRate(s: String): GT[F, Double]
}
FURTHER READINGFURTHER READING
Contains Chain and Validated, from the Cats
microsite
Cats Data Types
JOBS.DISNEYCAREERS.COMJOBS.DISNEYCAREERS.COM
@@mark canlas nycmark canlas nyc
1 of 124

Recommended

Composing an App with Free Monads (using Cats) by
Composing an App with Free Monads (using Cats)Composing an App with Free Monads (using Cats)
Composing an App with Free Monads (using Cats)Hermann Hueck
3K views89 slides
Implementing the IO Monad in Scala by
Implementing the IO Monad in ScalaImplementing the IO Monad in Scala
Implementing the IO Monad in ScalaHermann Hueck
1.3K views88 slides
Type Classes in Scala and Haskell by
Type Classes in Scala and HaskellType Classes in Scala and Haskell
Type Classes in Scala and HaskellHermann Hueck
1.4K views61 slides
ZIO-Direct - Functional Scala 2022 by
ZIO-Direct - Functional Scala 2022ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022Alexander Ioffe
762 views127 slides
Taking your side effects aside by
Taking your side effects asideTaking your side effects aside
Taking your side effects aside💡 Tomasz Kogut
715 views95 slides
Peeking inside the engine of ZIO SQL.pdf by
Peeking inside the engine of ZIO SQL.pdfPeeking inside the engine of ZIO SQL.pdf
Peeking inside the engine of ZIO SQL.pdfJaroslavRegec1
153 views55 slides

More Related Content

What's hot

non-strict functions, bottom and scala by-name parameters by
non-strict functions, bottom and scala by-name parametersnon-strict functions, bottom and scala by-name parameters
non-strict functions, bottom and scala by-name parametersPhilip Schwarz
1.2K views30 slides
ZIO: Powerful and Principled Functional Programming in Scala by
ZIO: Powerful and Principled Functional Programming in ScalaZIO: Powerful and Principled Functional Programming in Scala
ZIO: Powerful and Principled Functional Programming in ScalaWiem Zine Elabidine
544 views107 slides
The Functional Programming Triad of Map, Filter and Fold by
The Functional Programming Triad of Map, Filter and FoldThe Functional Programming Triad of Map, Filter and Fold
The Functional Programming Triad of Map, Filter and FoldPhilip Schwarz
3.5K views51 slides
Http4s, Doobie and Circe: The Functional Web Stack by
Http4s, Doobie and Circe: The Functional Web StackHttp4s, Doobie and Circe: The Functional Web Stack
Http4s, Doobie and Circe: The Functional Web StackGaryCoady
6.3K views33 slides
Lect 1-java object-classes by
Lect 1-java object-classesLect 1-java object-classes
Lect 1-java object-classesFajar Baskoro
2.1K views6 slides
Object and class by
Object and classObject and class
Object and classmohit tripathi
1.4K views44 slides

What's hot(20)

non-strict functions, bottom and scala by-name parameters by Philip Schwarz
non-strict functions, bottom and scala by-name parametersnon-strict functions, bottom and scala by-name parameters
non-strict functions, bottom and scala by-name parameters
Philip Schwarz1.2K views
ZIO: Powerful and Principled Functional Programming in Scala by Wiem Zine Elabidine
ZIO: Powerful and Principled Functional Programming in ScalaZIO: Powerful and Principled Functional Programming in Scala
ZIO: Powerful and Principled Functional Programming in Scala
The Functional Programming Triad of Map, Filter and Fold by Philip Schwarz
The Functional Programming Triad of Map, Filter and FoldThe Functional Programming Triad of Map, Filter and Fold
The Functional Programming Triad of Map, Filter and Fold
Philip Schwarz3.5K views
Http4s, Doobie and Circe: The Functional Web Stack by GaryCoady
Http4s, Doobie and Circe: The Functional Web StackHttp4s, Doobie and Circe: The Functional Web Stack
Http4s, Doobie and Circe: The Functional Web Stack
GaryCoady6.3K views
Lect 1-java object-classes by Fajar Baskoro
Lect 1-java object-classesLect 1-java object-classes
Lect 1-java object-classes
Fajar Baskoro2.1K views
Functional Programming 101 with Scala and ZIO @FunctionalWorld by Jorge Vásquez
Functional Programming 101 with Scala and ZIO @FunctionalWorldFunctional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorld
Jorge Vásquez446 views
Big picture of category theory in scala with deep dive into contravariant and... by Piotr Paradziński
Big picture of category theory in scala with deep dive into contravariant and...Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...
Piotr Paradziński840 views
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2 by Philip Schwarz
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Philip Schwarz1.3K views
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1 by Philip Schwarz
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Philip Schwarz1.9K views
Java Exception Handling and Applets by Tanmoy Roy
Java Exception Handling and AppletsJava Exception Handling and Applets
Java Exception Handling and Applets
Tanmoy Roy556 views
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming by John De Goes
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional ProgrammingZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming
John De Goes4.1K views
Sequence and Traverse - Part 1 by Philip Schwarz
Sequence and Traverse - Part 1Sequence and Traverse - Part 1
Sequence and Traverse - Part 1
Philip Schwarz3.2K views
Refactoring Functional Type Classes by John De Goes
Refactoring Functional Type ClassesRefactoring Functional Type Classes
Refactoring Functional Type Classes
John De Goes6.9K views

Similar to Functional Error Handling with Cats

Pragmatic Real-World Scala (short version) by
Pragmatic Real-World Scala (short version)Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)Jonas Bonér
72.8K views108 slides
Pragmatic Real-World Scala by
Pragmatic Real-World ScalaPragmatic Real-World Scala
Pragmatic Real-World Scalaparag978978
610 views108 slides
Beginning Scala Svcc 2009 by
Beginning Scala Svcc 2009Beginning Scala Svcc 2009
Beginning Scala Svcc 2009David Pollak
855 views18 slides
Achieving Parsing Sanity In Erlang by
Achieving Parsing Sanity In ErlangAchieving Parsing Sanity In Erlang
Achieving Parsing Sanity In ErlangSean Cribbs
832 views70 slides
More expressive types for spark with frameless by
More expressive types for spark with framelessMore expressive types for spark with frameless
More expressive types for spark with framelessMiguel Pérez Pasalodos
1.1K views72 slides
C# Cheat Sheet by
C# Cheat SheetC# Cheat Sheet
C# Cheat SheetGlowTouch
9K views1 slide

Similar to Functional Error Handling with Cats(20)

Pragmatic Real-World Scala (short version) by Jonas Bonér
Pragmatic Real-World Scala (short version)Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)
Jonas Bonér72.8K views
Pragmatic Real-World Scala by parag978978
Pragmatic Real-World ScalaPragmatic Real-World Scala
Pragmatic Real-World Scala
parag978978610 views
Beginning Scala Svcc 2009 by David Pollak
Beginning Scala Svcc 2009Beginning Scala Svcc 2009
Beginning Scala Svcc 2009
David Pollak855 views
Achieving Parsing Sanity In Erlang by Sean Cribbs
Achieving Parsing Sanity In ErlangAchieving Parsing Sanity In Erlang
Achieving Parsing Sanity In Erlang
Sean Cribbs832 views
Graph Database Query Languages by Jay Coskey
Graph Database Query LanguagesGraph Database Query Languages
Graph Database Query Languages
Jay Coskey1.4K views
Useful javascript by Lei Kang
Useful javascriptUseful javascript
Useful javascript
Lei Kang286 views
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf by Hiroshi Ono
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono370 views
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf by Hiroshi Ono
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono406 views
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf by Hiroshi Ono
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono524 views
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf by Hiroshi Ono
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono760 views
Round PEG, Round Hole - Parsing Functionally by Sean Cribbs
Round PEG, Round Hole - Parsing FunctionallyRound PEG, Round Hole - Parsing Functionally
Round PEG, Round Hole - Parsing Functionally
Sean Cribbs1.1K views
An overview of Python 2.7 by decoupled
An overview of Python 2.7An overview of Python 2.7
An overview of Python 2.7
decoupled248 views
Python 101++: Let's Get Down to Business! by Paige Bailey
Python 101++: Let's Get Down to Business!Python 101++: Let's Get Down to Business!
Python 101++: Let's Get Down to Business!
Paige Bailey1.8K views

Recently uploaded

Top-5-production-devconMunich-2023.pptx by
Top-5-production-devconMunich-2023.pptxTop-5-production-devconMunich-2023.pptx
Top-5-production-devconMunich-2023.pptxTier1 app
9 views40 slides
EV Charging App Case by
EV Charging App Case EV Charging App Case
EV Charging App Case iCoderz Solutions
9 views1 slide
Playwright Retries by
Playwright RetriesPlaywright Retries
Playwright Retriesartembondar5
6 views1 slide
JioEngage_Presentation.pptx by
JioEngage_Presentation.pptxJioEngage_Presentation.pptx
JioEngage_Presentation.pptxadmin125455
8 views4 slides
The Era of Large Language Models.pptx by
The Era of Large Language Models.pptxThe Era of Large Language Models.pptx
The Era of Large Language Models.pptxAbdulVahedShaik
7 views9 slides
Bootstrapping vs Venture Capital.pptx by
Bootstrapping vs Venture Capital.pptxBootstrapping vs Venture Capital.pptx
Bootstrapping vs Venture Capital.pptxZeljko Svedic
15 views17 slides

Recently uploaded(20)

Top-5-production-devconMunich-2023.pptx by Tier1 app
Top-5-production-devconMunich-2023.pptxTop-5-production-devconMunich-2023.pptx
Top-5-production-devconMunich-2023.pptx
Tier1 app9 views
JioEngage_Presentation.pptx by admin125455
JioEngage_Presentation.pptxJioEngage_Presentation.pptx
JioEngage_Presentation.pptx
admin1254558 views
Bootstrapping vs Venture Capital.pptx by Zeljko Svedic
Bootstrapping vs Venture Capital.pptxBootstrapping vs Venture Capital.pptx
Bootstrapping vs Venture Capital.pptx
Zeljko Svedic15 views
Automated Testing of Microsoft Power BI Reports by RTTS
Automated Testing of Microsoft Power BI ReportsAutomated Testing of Microsoft Power BI Reports
Automated Testing of Microsoft Power BI Reports
RTTS10 views
aATP - New Correlation Confirmation Feature.pptx by EsatEsenek1
aATP - New Correlation Confirmation Feature.pptxaATP - New Correlation Confirmation Feature.pptx
aATP - New Correlation Confirmation Feature.pptx
EsatEsenek1205 views
Generic or specific? Making sensible software design decisions by Bert Jan Schrijver
Generic or specific? Making sensible software design decisionsGeneric or specific? Making sensible software design decisions
Generic or specific? Making sensible software design decisions
Unlocking the Power of AI in Product Management - A Comprehensive Guide for P... by NimaTorabi2
Unlocking the Power of AI in Product Management - A Comprehensive Guide for P...Unlocking the Power of AI in Product Management - A Comprehensive Guide for P...
Unlocking the Power of AI in Product Management - A Comprehensive Guide for P...
NimaTorabi216 views
Transport Management System - Shipment & Container Tracking by Freightoscope
Transport Management System - Shipment & Container TrackingTransport Management System - Shipment & Container Tracking
Transport Management System - Shipment & Container Tracking
Freightoscope 5 views
Introduction to Git Source Control by John Valentino
Introduction to Git Source ControlIntroduction to Git Source Control
Introduction to Git Source Control
John Valentino7 views
How To Make Your Plans Suck Less — Maarten Dalmijn at the 57th Hands-on Agile... by Stefan Wolpers
How To Make Your Plans Suck Less — Maarten Dalmijn at the 57th Hands-on Agile...How To Make Your Plans Suck Less — Maarten Dalmijn at the 57th Hands-on Agile...
How To Make Your Plans Suck Less — Maarten Dalmijn at the 57th Hands-on Agile...
Stefan Wolpers42 views
How Workforce Management Software Empowers SMEs | TraQSuite by TraQSuite
How Workforce Management Software Empowers SMEs | TraQSuiteHow Workforce Management Software Empowers SMEs | TraQSuite
How Workforce Management Software Empowers SMEs | TraQSuite
TraQSuite6 views
AI and Ml presentation .pptx by FayazAli87
AI and Ml presentation .pptxAI and Ml presentation .pptx
AI and Ml presentation .pptx
FayazAli8714 views

Functional Error Handling with Cats