Cats и Cats Effects

Cats

Cats Book

Cats

Предоставя:

Data types

Синтаксис

Синтаксис – Option

import cats.syntax.option._

val maybeOne = 1.some // Some(1): Option[Int]
val maybeN = none[Int] // None: Option[Int]

val either = maybeOne.toRightNec("It's not there :(") // Right(1): Either[String, Int]
val validated = maybeOne.toValidNec("It's not there :(") // Left("..."): Either[String, Int]

val integer = maybeN.orEmpty // 0

Синтаксис – Either и Validated

import cats.syntax.either._

val eitherOne = 1.asRight
val eitherN = "Error".asLeft

val eitherOneChain = 1.rightNec
val eitherNChain = "Error".leftNec

val recoveredEither = eitherN.recover {
  case "Error" => 42.asRight
}

eitherOneChain.toValidated
import cats.syntax.validated._

val validatedOne = 1.validNec
val validatedN = "Error".invalidNec

validatedOne.toEither

Type class-ове

Поглед над йеархиите

Сравнение и наредба

trait Eq[A] {
  def eqv(x: A, y: A): Boolean

  def neqv(x: A, y: A): Boolean = !eqv(x, y)
}

Semigroup и Monoid

trait Semigroup[A] {
  def combine(x: A, y: A): A
}
trait Monoid[A] extends Semigroup[A] {
  def empty: A
}

Semigroup и Monoid синтаксис

import cats.syntax.monoid._

1 |+| 2 // 3
"ab".combineN(3) // "ababab"

0.isEmpty // true

Semigroup[Int].combineAllOption(List(1, 2, 3)) // Some(6)
Monoid[Int].combineAll(List(1, 2, 3)) // 6

Тестване на аксиоми

Foldable

trait Foldable[F[_]] {
  def foldLeft[A, B](fa: F[A], b: B)(f: (B, A) => B): B
  def foldRight[A, B](fa: F[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B]
}

  • Функтор
  • Апликатив
  • Монада

Functor

trait Functor[F[_]] {
  def map[A, B](fa: F[A])(f: A => B): F[B]
}

Apply

trait Apply[F[_]] extends Functor[F] {
  def ap[A, B](ff: F[A => B])(fa: F[A]): F[B]
  
  def product[A, B](fa: F[A], fb: F[B]): F[(A, B)] =
    ap(map(fa)(a => (b: B) => (a, b)))(fb)

  def map2[A, B, Z](fa: F[A], fb: F[B])(f: (A, B) => Z): F[Z] =
    map(product(fa, fb))(f.tupled)
}

Applicative

trait Applicative[F[_]] extends Apply[F] {
  def pure[A](x: A): F[A]

  def map[A, B](fa: F[A])(f: A => B): F[B] =
    ap(pure(f))(fa)
}

Traverse

trait Traverse[F[_]] extends Functor[F] with Foldable[F] {
  def traverse[G[_] : Applicative, A, B](fa: F[A])(f: A => G[B]): G[F[B]]

  def sequence[G[_]: Applicative, A](fga: F[G[A]]): G[F[A]] =
    traverse(fga)(ga => ga)
}

Apply, Applicative, Traverse синтаксис

FlatMap

trait FlatMap[F[_]] extends Apply[F] {
  def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B]
}

Monad

trait Monad[F[_]] extends FlatMap[F] with Applicative[F]

MonadError

trait MonadError[F[_], E] extends ApplicativeError[F, E] with Monad[F]

Абстрактни членове:

def raiseError[A](e: E): F[A]
def handleErrorWith[A](fa: F[A])(f: E => F[A]): F[A]

FlatMap, Monad и MonadError синтаксис

Parallel

trait Parallel[M[_]] extends NonEmptyParallel[M] {
  type F[_]
  
  def applicative: Applicative[F]
  def monad: Monad[M]

  def sequential: F ~> M
  def parallel: M ~> F
}

Композиция на функтор, апликатив и монада

Композиция на монади – OptionT и EitherT

Free Монада:

Cats Effect

“Framework to build composable typesafe functional concurrency libraries and applications.” – Cats Effect

Internals

  • JVM is all about threadpools
  • Modern concurrency isn’t
  • Fibers + Scheduler

How cats does it

  • A work-stealing pool for computation, consisting of exactly the same number of Threads as there are hardware processors (minimum: 2)
  • A single-threaded schedule dispatcher, consisting of a single maximum-priority Thread which dispatches sleeps with high precision
  • An unbounded blocking pool, defaulting to zero Threads and allocating as-needed (with caching and downsizing) to meet demand for blocking operations

https://typelevel.org/cats-effect/docs/schedulers

What we get is…

Cats Effect (демо)

Въпроси :)?

// reveal.js plugins