简体   繁体   中英

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)))

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]))

An alternative to the solution provided by Gabrielle. You can use the syntax provided by cats lib

import cats.syntax.option._ 

and then

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

Or 

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

10.some and none[Int] will be inferred to Option[Int]

PS: there is also a syntax for Either through cats.syntax.either._ 10.asRight[String] and "Oops".asLeft[Int] will be inferred to Either[String, Int]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM