HOME | EDIT | RSS | INDEX | ABOUT | GITHUB

Applied Category Theory in Scala

Choice

Choice

Rationale

usually we deal with function more often, we're so familiar with A => B

says if we have two function A => C and B => C

how can we compose them into a single function that can take either A or B and produce a C?

in Scala the return type will be like Either[A, B] => C

This is exactly Choice typeclass for, replacing => with F, you will get a Choice

trait Choice[F[_, _]] {
  def choice(fac: F[A, C], fbc: F[B, C]): F[Either[A, B], C]
}

Applied

A very useful case of Choice typeclass would be like middleware in HTTP server.

Take Http4s for example:

HttpRoutes[F]

http4s defined routes using Kleisli

type HttpRoutes[F[_]] = Kleisli[OptionT[F, ?], Request[F], Response[F]]
def routes[F[_]]: HttpRoutes[F] = ???

But before going through routes, most request must pass middleware to ensure the request has correct or not.

A authentication middleware could end up with 2 kinds of result

  1. return Unauthorized instantly while token is invalid
  2. Pass Request[F] through if token if valid

So the return type of middleware will be like Either[Response[F], Request[F]]

Middleware[F]

if we define middleware like

type Middleware[F[_]] = Kleisli[OptionT[F, ?], Request[F], Either[Response[F], Request[F]]]
val passThrough: Kleisli[OptionT[F, ?], Response[F], Response[F]] = Kleisli.ask[OptionT[F, ?], Response[F]]
def middleware[F[_]]: Middleware[F] = ???
61630772-ea415700-accb-11e9-9b4b-5abffa0d5bf4.png

Compose middleware and routes together is now easy thanks to Kleisli has instance of Choice

middleware andThen passThrough.choice(routes)