Skip to content

Instantly share code, notes, and snippets.

@programaker
Created November 8, 2021 17:38
Show Gist options
  • Save programaker/0da5e378c0ed30bcaefbfa639b5281fb to your computer and use it in GitHub Desktop.
Save programaker/0da5e378c0ed30bcaefbfa639b5281fb to your computer and use it in GitHub Desktop.

Revisions

  1. programaker created this gist Nov 8, 2021.
    70 changes: 70 additions & 0 deletions align.scala
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,70 @@
    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)