私は Scala のフリーモナドについて学んでおり、cats を使用してフリーモナドに持ち上げることができる代数の簡単な例をまとめました。
これが私の代数です
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 ()
しかし見た目は醜いし、気持ちが悪いです。
フリーモナドを使用するときにモナド効果をスタックする最も優れた方法は何ですか?
ベストアンサー1
このようなケースでよく見られる一般的な方法は、トラバース次のようにコードを変更できます。
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 ()
これは、私の意見では、モナド トランスフォーマーの代替手段よりもはるかにクリーンです。他のものが必要な場合がありimport
、コードを少し変更する必要があることに注意してください。試していませんが、概念は、traverse を使用することです。