I have a method which returns some ZIO:
def method(...): ZIO[Any with clock, SomeError, Unit]
The method which calls this return Task[Unit]:
def otherMethod(..): Task[Unit] = {
ZIO.effect(method(...))
}
The problem is when I call it with ZIO.effect I don't get result.
How I should convert ZIO to Task to get result?
With ZIO.effect(method(...)) you get back a Task[ZIO[...]] that is rarely what you want (it's conceptually similar to a nested Future[Future[A]]).
In order to turn a ZIO[R, E, A] into a Taks[A], you have to understand that the latter is just a type alias for ZIO[Any, Throwable, A], which suggest that you have to
eliminate the dependency on the environment R (by providing it)
turn the error type E to Throwable if it's not already a sub-type of it (e.g. by .mapError)
This should work:
def otherMethod(..): Task[Unit] =
method(...)
.mapError(someError => new RuntimeException(s"failed with: $someError"))
.provideLayer(Clock.live)
Related
I am trying to write a Cats MTL version of a function that would save an entity to a database. I want this function to read some SaveOperation[F[_]] from environment, execute it and handle possible failure. So far I came up with 2 version of this function: save is the more polymorphic MTL version and save2 uses exact monads in its signature, meaning that I confine myself to use of IO.
type SaveOperation[F[_]] = Employee => F[Int]
def save[F[_] : Monad](employee: Employee)(implicit
A: Ask[F, SaveOperation[F]],
R: Raise[F, AppError]): F[Unit] =
for {
s <- A.ask
rows <- s(employee)
res <- if rows != 1 then R.raise(FailedInsertion)
else ().pure[F]
} yield res
def save2(employee: Employee): Kleisli[IO, SaveOperation[IO], Either[AppError, Unit]] =
Kleisli((saveOperation) => saveOperation(employee)
.handleErrorWith(err => IO.pure(Left(PersistenceError(err))))
.map(rows =>
if rows != 1 then Left(FailedInsertion)
else Right(())
)
)
I can later call those like this:
val repo = new DoobieEmployeeRepository(xa)
val employee = Employee("john", "doe", Set())
type E[A] = Kleisli[IO, SaveOperation[IO], Either[AppError, A]]
println(EmployeeService.save[E](employee).run(repo.save).unsafeRunSync())
println(EmployeeService.save2(employee).run(repo.save).unsafeRunSync())
The problem is that for the call of save I get the following error:
Could not find an instance of Monad for E.
I found:
cats.data.Kleisli.catsDataMonadErrorForKleisli[F, A, E]
But method catsDataMonadErrorForKleisli in class KleisliInstances0_5 does not match type cats.Monad[E].
This error doesn't seem to make sense to me as effectively signatures are exactly the same for both function, so the monad should be there. I suspect the problem is with Ask[F, SaveOperation[F]] parameter as here F is not IO, while SaveOperation needs the IO.
Why can't I use the Kleisli monad for save call?
Update:
If I modify the type to type E[A] = EitherT[[X] =>> Kleisli[IO, SaveOperation[IO], X], AppError, A], I get a new error:
Could not find an implicit instance of Ask[E, SaveOperation[E]]
The right generic type for SaveOperation is supposed to be IO I guess, but I can't figure how to properly provide it through an instance of Ask
I hope you don't mind if I use this opportunity to do a quick tutorial on how to improve your question. It not only increases the chances of someone answering, but also might help you to find the solution yourself.
There are a couple of problems with the code you submitted, and I mean problems in terms of being a question on SO. Perhaps someone might have a ready answer just by looking at it, but let's say they don't, and they want to try it out in a worksheet. Turns out, your code has a lot of unnecessary stuff and doesn't compile.
Here are some steps you could take to make it better:
Strip away the unnecessary custom dependencies like Employee, DoobieEmployeeRepository, error types etc. and replace them with vanilla Scala types like String or Throwable.
Strip away any remaining code as long as you can still reproduce the problem. For example, the implementations of save and save2 are not needed, and neither are Ask and Raise.
Make sure that the code compiles. This includes adding the necessary imports.
By following these guidelines, we arrive at something like this:
import cats._
import cats.data.Kleisli
import cats.effect.IO
type SaveOperation[F[_]] = String => F[Int]
def save[F[_] : Monad](s: String)(): F[Unit] = ???
def save2(s: String): Kleisli[IO, SaveOperation[IO], Either[Throwable, Unit]] = ???
type E[A] = Kleisli[IO, SaveOperation[IO], Either[Throwable, A]]
println(save[E]("Foo")) // problem!
println(save2("Bar"))
That's already much better, because
a) it allows people to quickly try out your code, and
b) less code means less cognitive load and less space for problems.
Now, to check what's happening here, let's go to some docs:
https://typelevel.org/cats/datatypes/kleisli.html#type-class-instances
It has a Monad instance as long as the chosen F[_] does.
That's interesting, so let's try to further reduce our code:
type E[A] = Kleisli[IO, String, Either[Throwable, A]]
implicitly[Monad[E]] // Monad[E] doesn't exist
OK, but what about:
type E[A] = Kleisli[IO, String, A]
implicitly[Monad[E]] // Monad[E] exists!
This is the key finding. And the reason that Monad[E] doesn't exist in the first case is:
Monad[F[_]] expects a type constructor; F[_] is short for A => F[A] (note that this is actually Kleisli[F, A, A] :)). But if we try to "fix" the value type in Kleisli to Either[Throwable, A] or Option[A] or anything like that, then Monad instance doesn't exist any more. The contract was that we would provide the Monad typeclass with some type A => F[A], but now we're actually providing A => F[Either[Throwable, A]]. Monads don't compose so easily, which is why we have monad transformers.
EDIT:
After a bit of clarification, I think I know what you're going after now. Please check this code:
case class Employee(s: String, s2: String)
case class AppError(msg: String)
type SaveOperation[F[_]] = Employee => F[Int]
def save[F[_] : Monad](employee: Employee)(implicit
A: Ask[F, SaveOperation[F]],
R: Raise[F, AppError]): F[Unit] = for {
s <- A.ask
rows <- s(employee)
res <- if (rows != 1) R.raise(AppError("boom"))
else ().pure[F]
} yield res
implicit val askSaveOp = new Ask[IO, SaveOperation[IO]] {
override def applicative: Applicative[IO] =
implicitly[Applicative[IO]]
override def ask[E2 >: SaveOperation[IO]]: IO[E2] = {
val fun = (e: Employee) => IO({println(s"Saved $e!"); 1})
IO(fun)
}
}
implicit val raiseAppErr = new Raise[IO, AppError] {
override def functor: Functor[IO] =
implicitly[Functor[IO]]
override def raise[E2 <: AppError, A](e: E2): IO[A] =
IO.raiseError(new Throwable(e.msg))
}
save[IO](Employee("john", "doe")).unsafeRunSync() // Saved Employee(john,doe)!
I'm not sure why you expected Ask and Raise to already exist, they are referring to custom types Employee and AppError. Perhaps I'm missing something. So what I did here was that I implemented them myself, and I also got rid of your convoluted type E[A] because what you really want as F[_] is simply IO. There is not much point of having a Raise if you also want to have an Either. I think it makes sense to just have the code based around F monad, with Ask and Raise instances that can store the employee and raise error (in my example, error is raised if you return something other than 1 in the implementation of Ask).
Can you check if this is what you're trying to achieve? We're getting close. Perhaps you wanted to have a generic Ask defined for any kind of SaveOperation input, not just Employee? For what it's worth, I've worked with codebases like this and they can quickly blow up into code that's hard to read and maintain. MTL is fine, but I wouldn't want to go more generic than this. I might even prefer to pass the save function as a parameter rather than via Ask instance, but that's a personal preference.
I have a method
def getInfoFromService(reqParams: Map[String, String]): Future[Either[CustomException, A]]
and I have another function
import cats.implicits._
def processInfoAndModelResponse(input: Future[Either[CustomException, A]]): Option[A] = {
for {
either <- input
resultA <- either
} yield resultA.some
}
So basically, I am trying to convert Future[Either[CustomException, A]]) to Option[A]. The resultA <- either in above code would not work as map is not happy with type.
What you try to do is basically something like
def convert[A](future: Future[Either[CustomException, A]]): Option[A] =
Try(Await.result(future, timeout)).toEither.flatten.toOption
This:
looses information about error, which prevents any debugging (though you could log after .flatten)
blocks async operation which kills any benefit of using Future in the first place
Monads do not work like that. Basically you can handle several monadic calculations with for for the same monad, but Future and Either are different monads.
Try
import scala.concurrent.{Await, Future}
import scala.concurrent.duration._
def processInfoAndModelResponse(input: Future[Either[CustomException, A]]): Option[A] = {
Await.result(input, 1.minute).toOption
}
#MateuszKubuszok's answer is different in that it doesn't throw.
You can't sensibly convert a Future[Either[CustomException, A]] to Option[A], as you don't know what the result will be until the Future has completed.
Future[Either[CustomException, A]] might just bet kept that way, or put in IO as IO[Either[CustomException, A]]. If you don't care about CustomException, you can also capture it Future (or IO) error handling mechanisms, or just discard it entirely.
Some options:
absorb the CustomException in Future's error handling:
val fa: Future[A] = fut.transform(_.map(_.toTry))
ignore the CustomException an make the Future return with None
val fa: Future[Option[A]] = fut.map(_.toOption)
if you really want to block a thread and wait for the result,
Await.result(input, Duration.Inf).toOption
but all the caveats of awaiting apply. See the documentaion, reproduced here:
WARNING: It is strongly discouraged to supply lengthy timeouts since the progress of the calling thread will be suspended—blocked—until either the Awaitable has a result or the timeout expires.
I'm trying to write a Monad Transformer instance for ScalaCheck's Gen Type.
That is: a type such as the following, which could be used as a Monad, for provided that the underlying functor F is a Monad.
case class GeneratorT[F[_], A](generator: Gen[F[A]])
object GeneratorT {
implicit def monadForGeneratorT[F[_]: Monad]: Monad[GeneratorT[F, *]] = new Monad[GeneratorT[F, *]] {
...
}
}
While writing this, I realized that it would be useful if I was able to write a Distributive instance for Gen, because then I'd be able to write flatMap for GeneratorT in the following (somewhat convoluted) way:
override def flatMap[A, B](ga: GeneratorT[F, A])(fun: A => GeneratorT[F, B]): GeneratorT[F, B] = {
GeneratorT[F, B](ga.generator.flatMap(fa => fa.map(a => fun(a).generator).distribute(identity).map(_.flatten)))
}
Instinctively, I feel like I should be able to write a Distributive instance for Gen because Gen is more or less just a function from some configuration, and a seed, onto a value, and functions are distributive.
With that said, I've failed to find an example of anyone doing this, and I'm struggling to write it, because ScalaCheck doesn't expose the internals of Gen.
Is this possible?
I think I understand why this isn't quite possible; it's because Gen supports filtering, and as such, it's possible to end out with a Gen that has no valid values.
I was thinking of Gen as a function (Properties, Seed) => A, but actually, this should be more like (Properties, Seed) => Option[A].
The first type distributes, the second doesn't.
For example an IO[Gen[A]] can't be converted to a Gen[IO[A]] if the Gen might fail, because there's no way to know about the failure without evaluating the IO.
If you pretend that any Generator will produce a value if evaluated enough times, and you're willing to encounter exceptions when this isn't the case, it's possible to implement Distributive like so:
implicit val distributiveForGen: Distributive[Gen] = new Distributive[Gen] {
override def distribute[G[_]: Functor, A, B](ga: G[A])(f: A => Gen[B]): Gen[G[B]] =
Gen.parameterized(params => ga.map(a => f(a).pureApply(params, params.initialSeed.getOrElse(Seed(0)))))
override def map[A, B](fa: Gen[A])(f: A => B): Gen[B] = fa.map(f)
}
I'm fairly new to scalaz and I've started out with validations.
I have some validation functions of the form:
def validateXyz(...): ValidationNEL[String, String] = ...
I'm then using the applicative style to combine multiple validations and then call another function that also returns a validation:
(validateXyz(...) |#| validateAbc(...)) { (first, second) =>
otherFunction(first, second)
}
where,
def otherFunction(first: String, second: String): ValidationNEL[String, String] = ...
However, when calling the above the resulting type is:
val result: ValidationNEL[String, ValidationNEL[String, String]] = ...
I can unpack this by calling fold on the result with two functions, the first which just propagates the NEL as a fail and the second which just propagates its argument:
def propagateF(result: NonEmptyList[String]): ValidationNEL[String, String] = result.fail
def propagateV(result: ValidationNEL[String, String]) = result
result.fold(propagateF, propagateV)
// result type: ValidationNEL[String, String]
This works and returns the correct types and results. However it doesn't feel like the correct solution so I must be missing something. What do I need to do to avoid this horrible fold at the end?
What you are looking for here is monadic join.
The thing is that Validation itself is not really a monad, since the error side carries a Semigroup structure that cannot be preserved by Monad. But you can always drop down into the Either monad if you need to. This functionality is provided by flatMap.
(validateXyz(...) |#| validateAbc(...))(otherFunction).flatMap(x => x)
If you have an error on the outside, the result will be that error. If you have an error inside of a success, the result will be the inner error. Otherwise the result will be a success. Note the impossibility of having an error both on the inside and outside. This is why you have to use Applicative rather than Monad if you want to combine errors.
I am trying to get the grips of using Iteratees in Play 2 to stream comet results. I have got the handle go creating an enumerator from a callback and an enumeratee from a map.
My issue is with the Enumeratee.map, this takes a function that takes a pure input and returns a pure output (e.g. the String to Int conversion in the doc). What I would like to do is take a pure input and return a promise of a result.
After all, an enumerator feeds an enumeratee with promises, an enumeratee converts one enumerator to the other, so there should be a way to make an enumeratee that maps to promises.
Now, let me make an example to make this a bit clearer. Let's say that I have an http request coming in with a list of IDs to query in my database. Let's say that these ids represent rows in a database table and the request does a set of (long) computations on these rows and then returns a set of json objects representing the computation.
As I have long blocking stuff to do, it would be cool to stream that one ID at a time, so I would like to have an enumeratee pipeline that does:
query a row in the database (returns a promise of the row)
make a long computation on the row (takes a row and returns a promise of a computation)
convert the long computation to JSON
&> this out to the Comet enumeratee provided by Play 2
1 is kinda easy, I can construct an enumerator with a fromCallback that will return a promise of the query result.
3 is also kinda easy, as it's a simple Enumeratee.map
But I can't wrap my head around how to implement the applyOn of the enumeratee of step 2. I can of understood that I have bo build a new iteratee that get the promise from the "inner" iteratee, flatMap the long calculation and return the new promise. What I don't get is how to make this given the odd applyOn signature: def applyOn[A](it: Iteratee[To, A]): Iteratee[From, Iteratee[To, A]]
Can someone help me with that?
Thanks
There is a method on master Enumeratee.mapM[E] that takes f: E => Promise[NE] and returns Enumeratee[E, NE]
https://github.com/playframework/Play20/blob/master/framework/src/play/src/main/scala/play/api/libs/iteratee/Enumeratee.scala#L150
The signature of applyOn makes more sense when you think that the enumeratee combines with an iteratee on the right like in enumerator |>> (enumeratee &> iteratee). iteratee has type Iteratee[E, A] and enumerator expects a Iteratee[Promise[E], Iteratee[E, A] so that the inner iteratee can be extracted. So applyOn will have to a Iteratee[E, A] and return a Iteratee[Promise[E], Iteratee[E, A].
Here is the outline of an implementation. It defines a step function that takes an input and return the expected result. Then recursively steps through the promise elements.
import play.api.libs.concurrent._
import play.api.libs.iteratee._
def unpromise[E]: Enumeratee[Promise[E], E] = new Enumeratee[Promise[E], E] {
def applyOn[A](inner: Iteratee[E, A]): Iteratee[Promise[E], Iteratee[E, A]] = {
def step(input: Input[Promise[E]], i: Iteratee[E, A]): Iteratee[Promise[E], Iteratee[E, A]] = {
input match {
case Input.EOF => Done(i, Input.EOF)
case Input.Empty => Cont(step(_, i))
case Input.El(pe) =>
val pe2 = pe.map(e => i.feed(Input.El(e))).flatMap(identity)
val i2 = Iteratee.flatten(pe2)
i2.pureFlatFold(
(a, e2) => Done(i2, Input.Empty),
k => Cont(step(_, i2)),
(msg, e2) => Done(i2, Input.Empty))
}
}
// should check that inner is not done or error - skipped for clarity
Cont(step(_, inner))
}
}
I'm discarding e2, so there is probably more code to ensure some input is not lost.