Translate

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"))