Sto imparando la monade libera in Scala, e ho messo insieme un semplice esempio di algebra che posso sollevare in una monade libera usando i gatti.Impilare effetti monadici in una Monade libera in Scala
Ecco la mia algebra
sealed trait ConsultationOp[A]
object consultation {
case class Create(c: Consultation) extends ConsultationOp[Unit]
case class Get(s: ConsultationId) extends ConsultationOp[Option[Consultation]]
}
E io sono in grado di usarlo come
def app = for {
c <- consultation.Create(Consultation("123", "A consultation"))
_ <- consultation.Get(c._id)
} yield()
def interpreters = ConsultationInterpreter or UserInterpreter
app.foldMap(interpreters)
Quando è effettuata implicitamente il sollevamento ConsultationOp
-Free
.
(c'è un sacco di dettagli mancanti, l'implementazione di lavoro completo è qui: https://github.com/gabro/free-api)
Fin qui tutto bene, ma se ho bisogno di estrarre il valore opzionale restituito da consultation.Get
.
La prima cosa che viene in mente è un trasformatore Monade, vale a dire qualcosa come
def app = for {
c <- consultation.Create(Consultation("123", "A consultation")).liftM[OptionT]
d <- OptionT(consultation.Get(c._id))
_ <- doSomethingAConsultation(d)
} yield()
ma sembra brutto, e non mi sembra giusto.
Qual è il modo glorificato, se esiste, di impilare effetti monadici quando si utilizza una monade libera?
C'è una discussione relativa a questo [qui] (https://www.reddit.com/r/scala/comments/5p3fc3/free_monads_in_scala_web_stack_part_i/dco5yqy/). L'essenziale è che l'utilizzo di Free non ti libera dalla gestione del valore 'A' in' ConsultationOp'. Esistono librerie come [freek] (https://github.com/ProjectSeptemberInc/freek) e [eff] (https://github.com/atnos-org/eff) che risolvono il problema in modo più elegante. –