Search code examples
scalascala-cats

Scala Cats Lifting values into Monad Transformers


I am reading this documentation about lifting values into Monad Transformers.

Based on this I wrote the following code

import cats.data._
import cats.implicits._
type FutureOption[T] = OptionT[Future, T]
val x : FutureOption[Int] = 1.pure[FutureOption] // works
val y : FutureOption[Int] = OptionT.fromOption[Future](Some(10)) // works
val z : FutureOption[Int] = OptionT.liftF(Future.successful(10)) // works

Now if I try

val z = FutureOption[Int] = OptionT(Future.successful(Some(10)))

I get an error

cmd4.sc:1: no type parameters for method apply: (value: F[Option[A]])cats.data.OptionT[F,A] in object OptionT exist so that it can be applied to arguments (scala.concurrent.Future[Some[Int]])
 --- because ---
argument expression's type is not compatible with formal parameter type;
 found   : scala.concurrent.Future[Some[Int]]
 required: ?F[Option[?A]]
val x : OptionT[Future, Int] = OptionT(Future.successful(Some(10)))
                               ^
cmd4.sc:1: type mismatch;
 found   : scala.concurrent.Future[Some[Int]]
 required: F[Option[A]]
val x : OptionT[Future, Int] = OptionT(Future.successful(Some(10)))
                                                        ^
cmd4.sc:1: type mismatch;
 found   : cats.data.OptionT[F,A]
 required: cats.data.OptionT[scala.concurrent.Future,Int]
val x : OptionT[Future, Int] = OptionT(Future.successful(Some(10)))

Solution

  • The error is due to Scala type inference.

    In absence of an explicit Option type annotation, the type of Some(10) is Some[Int] which is a subtype of Option[Int]. However OptionT expects exactly Option so it won't compile.

    You can make it compile by doing

    val z: FutureOption[Int] = OptionT(Future.successful(Option(10)))
    

    or

    val z: FutureOption[Int] = OptionT(Future.successful(Some(10): Option[Int]))