I'm trying to use Scalaz EitherT with a scala.concurrent.Future. When trying to use it in a for-comprehension:
import scalaz._
import Scalaz._
val et1:EitherT[Future, String, Int] = EitherT(Future.successful(1.right))
val et2:EitherT[Future, String, String] = EitherT(Future.successful("done".right))
val r:EitherT[Future, String, String] = for {
a <- et1
b <- et2
} yield (s"$a $b")
I get the following missing Functor and Monad instances error:
could not find implicit value for parameter F: scalaz.Functor[scala.concurrent.Future]
b <- et2
^
could not find implicit value for parameter F: scalaz.Monad[scala.concurrent.Future]
a <- et1
Does scalaz define instances for Functor and Monad for Future? If not are there any other libraries that provide these instances or do I need to write them?
You need an implicit ExecutionContext
in scope. import ExecutionContext.Implicits.global
will get you the global execution context.
Full example:
import scala.concurrent.ExecutionContext.Implicits.global
import scalaz._
import Scalaz._
val et1:EitherT[Future, String, Int] = EitherT(Future.successful(1.right))
val et2:EitherT[Future, String, String] = EitherT(Future.successful("done".right))
val r:EitherT[Future, String, String] = for {
a <- et1
b <- et2
} yield s"$a $b"
val foo = Await.result(r.run, 1 seconds)
// => \/-("1 done")
The error is not because of ExecutionContext is missing (it's needed though) but because Scala Future is not a Functor nor a Monad.
The accepted solution works not because of the ExecutionContext but because it imports all the implicits from Scalaz.
This is the line that really fix the problem:
import Scalaz._
Also note that using the global execution context it's ok for a test but should not be used on production deployments.
The problem with that solution is that you import ALL the implicits defined on the library and can make your IDE little bit slow.
On version 7 Scalaz offer the option to import only what you need, using the package scalaz.syntax
.
Same previous solution with concrete imports:
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import scalaz._
import scalaz.std.scalaFuture._
import scalaz.syntax.either._
val et1:EitherT[Future, String, Int] = EitherT(Future.successful(1.right))
val et2:EitherT[Future, String, String] = EitherT(Future.successful("done".right))
val r:EitherT[Future, String, String] = for {
a <- et1
b <- et2
} yield s"$a $b"
val foo = Await.result(r.run, 1 seconds)
foo: String \/ String = \/-(1 done)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With