jueves, 21 de julio de 2022

Mónadas en Cats parte 18

El log en un Writer se conserva cuando hacemos map or flatMap sobre él. flatMap agrega los logs del Writer de origen y el resultado de la función de secuenciación del usuario. Por esta razón, es una buena práctica utilizar un tipo de registro que tenga operaciones de adición y concatenación eficientes, como un Vector:

val writer1 = for {

    a <- 10.pure[Logged]

    _ <- Vector("a", "b", "c").tell

    b <- 32.writer(Vector("x", "y", "z"))

} yield a + b

// writer1: cats.data.WriterT[cats.package.Id, Vector[String], Int] =WriterT(

//(Vector("a", "b", "c", "x", "y", "z"), 42)

// )

writer1.run

// res3: (Vector[String], Int) = (Vector("a", "b", "c", "x", "y", "z") , 42)


Además de transformar el resultado con map y flatMap, podemos transformar el log en un Writer con el método mapWritten:


val writer2 = writer1.mapWritten(_.map(_.toUpperCase))

// writer2: cats.data.WriterT[cats.package.Id, Vector[String], Int] = WriterT(

// (Vector("A", "B", "C", "X", "Y", "Z"), 42)

// )

writer2.run

// res4: (Vector[String], Int) = (Vector("A", "B", "C", "X", "Y", "Z") , 42)


Podemos transformar tanto el log como el resultado simultáneamente usando bimap o mapBoth. bimap toma dos parámetros de función, uno para el registro y otro para el resultado. mapBoth toma una sola función que acepta dos parámetros:


val writer3 = writer1.bimap(

    log => log.map(_.toUpperCase),

    res => res * 100

)

// writer3: cats.data.WriterT[cats.package.Id, Vector[String], Int] = WriterT(

//(Vector("A", "B", "C", "X", "Y", "Z"), 4200)

// )

writer3.run

// res5: (Vector[String], Int) = (Vector("A", "B", "C", "X", "Y", "Z"), 4200)

val writer4 = writer1.mapBoth { (log, res) =>

    val log2 = log.map(_ + "!")

    val res2 = res * 1000

    (log2, res2)

}

// writer4: cats.data.WriterT[cats.package.Id, Vector[String], Int] =WriterT(

//(Vector("a!", "b!", "c!", "x!", "y!", "z!"), 42000)

// )

writer4.run

// res6: (Vector[String], Int) = (

//Vector("a!", "b!", "c!", "x!", "y!", "z!"),

//42000

// )


Finalmente, podemos borrar el registro con el método de reinicio e intercambiar el registro y el resultado con el método de intercambio:


val writer5 = writer1.reset

// writer5: cats.data.WriterT[cats.package.Id, Vector[String], Int] = WriterT(

//(Vector(), 42)

// )

writer5.run

// res7: (Vector[String], Int) = (Vector(), 42)

val writer6 = writer1.swap

// writer6: cats.data.WriterT[cats.package.Id, Int, Vector[String]] = WriterT(

//(42, Vector("a", "b", "c", "x", "y", "z"))

// )

writer6.run

// res8: (Int, Vector[String]) = (42, Vector("a", "b", "c", "x", "y","z"))

No hay comentarios.:

Publicar un comentario