Created
November 8, 2021 17:38
-
-
Save programaker/0da5e378c0ed30bcaefbfa639b5281fb to your computer and use it in GitHub Desktop.
The Align typeclass
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import scala.util.Try | |
import cats.Functor | |
import cats.Align | |
import cats.data.Ior | |
type Decimal = Int | |
type Roman = String | |
def f[F[_]: Align: Functor](fi: F[Decimal], fs: F[Roman]): F[String] = | |
import cats.syntax.align.* // <- HERE | |
import cats.syntax.functor.* | |
// `align` is like a "zip on steroids"! | |
// It pairs 2 effects regardless whether they are symmetric or not | |
// i.e they have the same size, they are both defined, they are both successful, etc. | |
// | |
// The `Align` typeclass provides more interesting "zippers" like this. | |
// Check them out! https://typelevel.org/cats/api/cats/Align.html | |
fi.align(fs).map { ior => | |
ior match | |
case Ior.Both(decimal, roman) => s"$decimal is $roman in Roman" | |
case Ior.Left(decimal) => s"$decimal has no Roman" | |
case Ior.Right(roman) => s"$roman has no Decimal" | |
} | |
/// | |
val decimals1 = List(1, 2, 3, 0) | |
val romans1 = List("I", "II", "III") | |
val out1 = f(decimals1, romans1) | |
// List[String] = List(1 is I in Roman, 2 is II in Roman, 3 is III in Roman, 0 has no Roman) | |
val decimals2 = List(1, 2, 3) | |
val romans2 = List("I", "II", "III", "IV") | |
val out1a = f(decimals2, romans2) | |
// List[String] = List(1 is I in Roman, 2 is II in Roman, 3 is III in Roman, IV has no Decimal) | |
val out1b = f(List.empty, List.empty) | |
// List[String] = List() | |
/// | |
import cats.syntax.option.* | |
val out2 = f(0.some, None) | |
// Option[String] = Some(1 is I in Roman) | |
val out2a = f(1.some, "I".some) | |
// Option[String] = Some(1 is I in Roman) | |
val out2b = f(None, "X".some) | |
// Option[String] = Some(X has no Decimal) | |
val out2c = f(None, None) | |
/// | |
type Either_[A] = Either[String, A] | |
val out3 = f(Right(1), Left("ERROR")) | |
// Either[String, String] = Right(1 has no Roman) | |
val out3a = f[Either_](Right(1), Right("I")) | |
// Either[String, String] = Right(1 is I in Roman) | |
val out3b = f(Left("ERROR"), Right("X")) | |
// Either[String, String] = Right(X has no Decimal) | |
val out3c = f[Either_](Left("ERROR"), Left("ERROR")) | |
// Either[String, String] = Left(ERROR) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment