Я изучаю свободную монаду в Scala, и я собрал простой пример алгебры, который я могу поднять в Free monad, используя кошек.
Здесь моя алгебра
sealed trait ConsultationOp[A]
object consultation {
case class Create(c: Consultation) extends ConsultationOp[Unit]
case class Get(s: ConsultationId) extends ConsultationOp[Option[Consultation]]
}
И я могу использовать его как
def app = for {
c <- consultation.Create(Consultation("123", "A consultation"))
_ <- consultation.Get(c._id)
} yield ()
def interpreters = ConsultationInterpreter or UserInterpreter
app.foldMap(interpreters)
Если подстановка с ConsultationOp
до Free
выполняется неявно.
(там много деталей отсутствует, полная рабочая реализация здесь: https://github.com/gabro/free-api)
Пока все хорошо, но что, если мне нужно извлечь необязательное значение, возвращаемое consultation.Get
.
Первое, что приходит в голову, это трансформатор монады, т.е. что-то вроде
def app = for {
c <- consultation.Create(Consultation("123", "A consultation")).liftM[OptionT]
d <- OptionT(consultation.Get(c._id))
_ <- doSomethingAConsultation(d)
} yield ()
но он выглядит уродливым, и он не чувствует себя хорошо.
Какой прославленный путь - если таковой имеется - укладывания монадических эффектов при использовании свободной монады?