Uczę się o Darmowej Monadzie w Scali, a ja stworzyłem prosty przykład algebry, którą mogę podnieść do wolnej monady używając kotów.Układanie monadycznych efektów w Free Monadzie w Scali
Oto mój algebra
sealed trait ConsultationOp[A]
object consultation {
case class Create(c: Consultation) extends ConsultationOp[Unit]
case class Get(s: ConsultationId) extends ConsultationOp[Option[Consultation]]
}
I jestem w stanie używać go jak
def app = for {
c <- consultation.Create(Consultation("123", "A consultation"))
_ <- consultation.Get(c._id)
} yield()
def interpreters = ConsultationInterpreter or UserInterpreter
app.foldMap(interpreters)
Gdzie zniesienie od ConsultationOp
do Free
jest wykonywana w sposób dorozumiany.
(tam jest dużo informacji brakuje, pełne wdrożenie pracy jest tutaj: https://github.com/gabro/free-api)
Jak na razie dobrze, ale co jeśli trzeba wyodrębnić opcjonalnego wartość zwracana przez consultation.Get
.
Pierwszą rzeczą, która przychodzi do głowy, to transformator monada, czyli coś jak
def app = for {
c <- consultation.Create(Consultation("123", "A consultation")).liftM[OptionT]
d <- OptionT(consultation.Get(c._id))
_ <- doSomethingAConsultation(d)
} yield()
ale wygląda brzydki, i to nie w porządku.
Jaki jest uwielbiony sposób - jeśli w ogóle - ułożenia monadycznych efektów podczas używania monady Free?
Istnieje dyskusja związana z tym [tutaj] (https://www.reddit.com/r/scala/comments/5p3fc3/free_monads_in_scala_web_stack_part_i/dco5yqy/). Istotą jest to, że użycie opcji Wolny nie zwalnia cię z obsługi wartości 'A' w' ConsultationOp'. Istnieją biblioteki takie jak [freek] (https://github.com/ProjectSeptemberInc/freek) i [eff] (https://github.com/atnos-org/eff), które rozwiązują ten problem bardziej elegancko. –