Scala の Future を Monix Task に変換したかった。
公式リファレンスにチュートリアル動画があったので視聴メモ。
準備
Future を返す関数のサンプル
この関数を、如何にして Monix Task へ変換するかという点について解説する。
def sum(list: List[Int])(implicit ec: ExecutionContext): Future[Long] =
Future(list.foldLeft(0L)(_ + _))
本題
Task.fromFuture を使う
Future.apply が実行されるので遅延したい場合は使わないこと。
def sumTask(list: List[Int])(implicit ec: ExecutionContext): Task[Long] =
Task.fromFuture(sum(list))
Task.suspend もしくは Task.deferFuture を使う
suspend は defer のエイリアス なので suspend が Future を扱った場合、 deferFuture と同義となる。
Task.suspend
def sumTask(list: List[Int])(implicit ec: ExecutionContext): Task[Long] =
Task.suspend {
Task.fromFuture(sum(list))
}
Task.deferFuture
def sumTask(list: List[Int])(implicit ec: ExecutionContext): Task[Long] =
Task.deferFuture(sum(list))
Task.deferFutureAction を使う
コールバックにインジェクトされた Scheduler を暗黙知として受け取る。
メソッドのシグネチャから ExecutionContext の暗黙引数が消えるは良さそう。
def sumTask(list: List[Int]): Task[Long] =
Task.deferFutureAction { implicit scheduler =>
sum(list)
}
.runToFuture する際、 Implicit Parameter に Scheduler を渡して利用する。
import monix.execution.Scheduler.Implicits.global
sumTask(List(1,2,3)).runToFuture
FutureLift を使う
Future → Task だけでなく他の非同期系の型変換をサポートしている。
※まだ、詳しく調べられていない。
FutureLift.from を使う
Task.from 同様 Future.apply は遅延しないことに注意。
def sumTask(list: List[Int])(implicit ec: ExecutionContext): Task[Long] =
FutureLift.from(Task(sum(list)))
他の非同期系の型(cats.effect.IO)への変換は下記の通り。
def sumTask(list: List[Int])(implicit ec: ExecutionContext): IO[Long] =
FutureLift.from(IO(sum(list)))
Task.deferAction と組み合わせて使う
Future.apply は遅延するし、シグネチャから ExecutionContext も消えた。
def sumTask(list: List[Int]): Task[Long] =
Task.deferAction { implicit s =>
FutureLift.from(Task(sum(list)))
}
以上、Future → Monix.Task へのお引っ越しを検討中の方の参考になれば幸いです。