Scalaのフリーモナドでモナド効果を積み重ねる 質問する

Scalaのフリーモナドでモナド効果を積み重ねる 質問する

私は 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 を使用することです。

おすすめ記事