実コードでは引数の依存や仕様で順番は変えられないものを想定
OptionTを使わない場合と使う場合のコード例
for式を二重にする方法は取り出した値がOptionに包まれた状態で、次のgeneratorで利用できないためここでは触れない
import scalaz.OptionT
import scala.concurrent.{Await, ExecutionContext, Future}
import scala.concurrent.duration.Duration
object Hello extends App {
import scala.concurrent.ExecutionContext.Implicits.global
import scalaz.Scalaz._
import Factories._
// 実コードでは引数の依存や仕様で順番は変えられないものを想定
private val option: Option[String] = Option("hoge")
private val futureOption: Future[Option[String]] = Future.successful(Some("fuga"))
private val future: Future[Piyo] = Future.successful(Piyo("piyo", "piyo"))
private val futureOption2: Future[Option[String]] = Future.successful(Some("moge"))
// OptionTを使わない場合
val futureOptionString: Future[Option[String]] = option
.map(
hoge =>
futureOption.flatMap(
_.map(
fuga =>
future.flatMap {
case Piyo(piyo, piyopiyo) =>
futureOption2.map(_.map(moge => s"$hoge $fuga $piyo $piyopiyo $moge"))
}
).getOrElse(Future.successful(None))
)
).getOrElse(Future.successful(None))
val res1: Option[String] = Await.result(futureOptionString, Duration.Inf)
// OptionTを使った場合
val optionT: OptionT[Future, String] = for {
hoge <- option.toOptionT
fuga <- futureOption.toOptionT
Piyo(piyo, piyopiyo) <- future.toOptionT
moge <- futureOption2.toOptionT
} yield {
s"$hoge $fuga $piyo $piyopiyo $moge"
}
val res2: Option[String] = Await.result(optionT.run, Duration.Inf)
println(res1 == res2)
}
object Factories {
import scalaz._
implicit class RichOption[A](val opt: Option[A]) {
def toOptionT(implicit ec: ExecutionContext): OptionT[Future, A] = OptionT(Future.successful(opt))
}
implicit class RichFutureOption[A](val f: Future[Option[A]]) {
def toOptionT(implicit ec: ExecutionContext): OptionT[Future, A] = OptionT(f)
def toOptionTOption(implicit ec: ExecutionContext): OptionT[Future, Option[A]] = OptionT(f.map(Option(_)))
}
implicit class RichFuture[A](val f: Future[A]) {
def toOptionT(implicit ec: ExecutionContext): OptionT[Future, A] = OptionT(f.map(Option(_)))
}
}
case class Piyo(piyo: String, piyopiyo: String)