Como hemos visto con Reader y Writer, el poder de la mónada State proviene de la combinación de instancias. Los métodos map y flatMap enhebran el estado de una instancia a otra. Cada instancia individual representa una transformación de estado atómico, y su combinación representa una secuencia completa de cambios:
val step1 = State[Int, String]{ num =>
val ans = num + 1
(ans, s"Result of step1: $ans")
}
val step2 = State[Int, String]{ num =>
val ans = num * 2
(ans, s"Result of step2: $ans")
}
val both = for {
a <- step1
b <- step2
} yield (a, b)
val (state, result) = both.run(20).value
// state: Int = 42
// result: (String, String) = ("Result of step1: 21", "Result of step2: 42")
Como puedes ver, en este ejemplo el estado final es el resultado de aplicar ambas transformaciones en secuencia. El estado se entrelaza paso a paso, aunque no interactuamos con él. El modelo general para usar la mónada de estado es representar cada paso de un cálculo como una instancia y componer los pasos usando los operadores de mónada estándar. Cats proporciona varios constructores de conveniencia para crear pasos primitivos:
- get extrae el estado como resultado;
- set actualiza el estado y devuelve la unidad como resultado;
- pure ignora el estado y devuelve un resultado proporcionado;
- inspect extrae el estado a través de una función de transformación;
- modify actualiza el estado utilizando una función de actualización.