scala - monadologia - monadas filosofia
Apilamiento de efectos monádicos en una mónada libre en Scala (1)
La forma común en que veo que se repite en estos casos es usar el desplazamiento , para que puedas cambiar tu código de la siguiente manera:
import cats.syntax.traverse._
import cats.instances.option._
// ...
def app = for {
c <- consultation.Create(Consultation("123", "A consultation"))
d <- consultation.Get(c._id)
_ <- d.traverseU(doSomethingAConsultation(_))
} yield ()
Lo cual, imho, es mucho más limpio que la alternativa de transformador de mónada. Tenga en cuenta que podría necesitar algún otro tipo de import
y modificar ligeramente el código, no lo probé, pero el concepto es: usar traverse.
Estoy aprendiendo acerca de la mónada gratis en Scala, y he reunido un ejemplo simple de álgebra que puedo incorporar a una mónada gratuita usando gatos.
Aquí está mi álgebra
sealed trait ConsultationOp[A]
object consultation {
case class Create(c: Consultation) extends ConsultationOp[Unit]
case class Get(s: ConsultationId) extends ConsultationOp[Option[Consultation]]
}
Y soy capaz de usarlo como
def app = for {
c <- consultation.Create(Consultation("123", "A consultation"))
_ <- consultation.Get(c._id)
} yield ()
def interpreters = ConsultationInterpreter or UserInterpreter
app.foldMap(interpreters)
Donde el levantamiento de ConsultationOp
a Free
se realiza implícitamente.
(faltan muchos detalles, la implementación completa está aquí: https://github.com/gabro/free-api )
Hasta ahora todo bien, pero ¿qué pasa si necesito extraer el valor opcional devuelto por la consultation.Get
? consultation.Get
.
Lo primero que viene a la mente es un transformador de mónada, es decir, algo así como
def app = for {
c <- consultation.Create(Consultation("123", "A consultation")).liftM[OptionT]
d <- OptionT(consultation.Get(c._id))
_ <- doSomethingAConsultation(d)
} yield ()
pero se ve feo, y no se siente bien.
¿Cuál es la forma glorificada, si existe, de apilar efectos monádicos cuando se usa una mónada libre?