Pregunta ¿Es el escritor Mónada efectivamente el mismo que el Estado Mónada?


Hay un gran tutorial aquí eso parece sugerirme que Writer Monad es básicamente un objeto de tupla de caso especial que realiza operaciones en nombre de (A, B). El escritor acumula valores a la izquierda (que es A) y que A tiene un Monoid correspondiente con él (por lo tanto, puede acumular o mutar el estado). Si A es una colección, entonces se acumula.

La Mónada de Estado también es un objeto que trata con una tupla interna. Ambos pueden ser planos, mapeados, etc. Y las operaciones me parecen iguales. ¿En qué se diferencian? (por favor responda con un ejemplo de scala, no estoy familiarizado con Haskel). ¡Gracias!


19
2018-05-29 20:58


origen


Respuestas:


Su intuición de que estas dos mónadas están estrechamente relacionadas es exactamente correcta. La diferencia es que Writer es mucho más limitado, ya que no le permite leer el estado acumulado (hasta que retire el dinero al final). Lo único que puedes hacer con el estado en una Writer es más cosas al final.

Más concisamente, State[S, A] es una especie de envoltorio para S => (S, A), mientras Writer[W, A] es un envoltorio para (W, A).

Considere el siguiente uso de Writer:

import scalaz._, Scalaz._

def addW(x: Int, y: Int): Writer[List[String], Int] =
  Writer(List(s"$x + $y"), x + y)

val w = for {
  a <- addW(1, 2)
  b <- addW(3, 4)
  c <- addW(a, b)
} yield c

Ahora podemos ejecutar el cálculo:

scala> val (log, res) = w.run
log: List[String] = List(1 + 2, 3 + 4, 3 + 7)
res: Int = 10

Podríamos hacer exactamente lo mismo con State:

def addS(x: Int, y: Int) =
  State((log: List[String]) => (log |+| List(s"$x + $y"), x + y))

val s = for {
  a <- addS(1, 2)
  b <- addS(3, 4)
  c <- addS(a, b)
} yield c

Y entonces:

scala> val (log, res) = s.run(Nil)
log: List[String] = List(1 + 2, 3 + 4, 3 + 7)
res: Int = 10

Pero esto es un poco más detallado, y también podríamos hacer un montón de otras cosas con State que no podríamos hacer con Writer.

Entonces, la moraleja de la historia es que deberías usar Writer siempre que pueda, su solución será más clara, más concisa y obtendrá la satisfacción de haber utilizado la abstracción adecuada.

Muy a menudo Writer no le dará todo el poder que necesita, sin embargo, y en esos casos State Estaré esperandote.


35
2018-05-29 22:10



tl; dr State es Leer y Escribir mientras Writer es, bueno, solo escribir.

Con State tiene acceso a los datos anteriores almacenados y puede usar estos datos en su cálculo actual:

def myComputation(x: A) =
  State((myState: List[A]) => {
        val newValue = calculateNewValueBasedOnState(x,myState)
        (log |+| List(newValue), newValue)
  })

Con Writer puede almacenar datos en algún objeto al que no tiene acceso, solo puede escribir en ese objeto.


0
2017-10-27 07:32