Translate

domingo, 22 de mayo de 2022

Mónadas en Cats parte 7

 La sintaxis de las mónadas proviene de tres lugares:

  • cats.syntax.flatMap proporciona sintaxis para flatMap;
  • cats.syntax.functor proporciona sintaxis para el map;
  • cats.syntax.applicative proporciona sintaxis para pure.
En la práctica, a menudo es más fácil importar todo de una sola vez desde cats.implicits. Sin embargo, usaremos las importaciones individuales aquí para mayor claridad.

Podemos usar pure para construir instancias de una mónada. A menudo necesitaremos especificar el parámetro de tipo para eliminar la ambigüedad de la instancia particular que queremos.

import cats.instances.option._  // for Monad
import cats.instances.list._ // for Monad
import cats.syntax.applicative._ // for pure

1.pure[Option]
// res5: Option[Int] = Some(1)
1.pure[List]
// res6: List[Int] = List(1)

Es difícil demostrar los métodos flatMap y map directamente en las mónadas de Scala como Option y List, porque definen sus propias versiones explícitas de esos métodos. En su lugar, escribiremos una función genérica que realice un cálculo en los parámetros que vienen envueltos en una mónada a elección del usuario:

import cats.Monad
import cats.syntax.functor._ // for map
import cats.syntax.flatMap._ // for flatMap

def sumSquare[F[_]: Monad](a: F[Int], b: F[Int]): F[Int] = a.flatMap(x => b.map(y => x*x + y*y))

import cats.instances.option._ // for Monad
import cats.instances.list._  // for Monad

sumSquare(Option(3), Option(4))
// res7: Option[Int] = Some(25)

sumSquare(List(1, 2, 3), List(4, 5))
// res8: List[Int] = List(17, 26, 20, 29, 25, 34)

Podemos reescribir este código usando comprensiones. El compilador "hará lo correcto" reescribiendo nuestra comprensión en términos de flatMap y map e insertando las conversiones implícitas correctas para usar nuestra Monad:

def sumSquare[F[_]: Monad](a: F[Int], b: F[Int]): F[Int] =
for {
    x <- a
    y <- b
} yield x*x + y*y

sumSquare(Option(3), Option(4))
// res10: Option[Int] = Some(25)

sumSquare(List(1, 2, 3), List(4, 5))
// res11: List[Int] = List(17, 26, 20, 29, 25, 34)

Eso es más o menos todo lo que necesitamos saber sobre las generalidades de las mónadas en Cats.