Scalaz: what role does filtering play in | @ |?

We used WriterT's monad transformer on Futures, hoping to get more organized magazines from an asynchronous application, but we ran into some problems.

If I compile the application below, I get the following error. Please note that this is not a warning about the Filter file.

[error] The filter is not a member of scalaz.WriterT [scala.concurrent.Future, List [String], String]

Why | @ | need a filter here? Does Scalaz provide implicit conversion for this case?

import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future import scalaz._ import Scalaz._ object Failure extends App { type LoggedT[F[_], A] = WriterT[F, List[String], A] type LoggedFuture[A] = LoggedT[Future, A] //this is the applicative behavior that we want WriterT to preserve val example = for { z <- (Future("left") |@| Future("right")) { (x: String, y: String) => x + " " + y } } yield z example.onSuccess { case x => println(x) } val test = for { z: String <- (Future("left").liftM[LoggedT] |@| Future("right").liftM[LoggedT]) { (x: String, y: String) => x + " " + y } } yield z test.value.onSuccess { case x => println(x) } } 

The error occurs with Scala version: 2.11.7 and Scalaz version: 7.2.0

+5
source share
1 answer

It is often useful to use the reify reflection library to see what happens during desugaring (this is the only time I suggest importing something from scala.reflect.runtime , and even then only into REPL during development)

 scala> import scala.reflect.runtime.universe.reify import scala.reflect.runtime.universe.reify scala> reify(for { x: Int <- Option(1) } yield x) res5: reflect.runtime.universe.Expr[Option[Int]] = Expr[scala.Option[Int]](Option.apply(1).withFilter(((check$ifrefutable$1) => check$ifrefutable$1: @unchecked match { case (x @ (_: Int)) => true case _ => false })).map(((x: Int) => x))) 

The problem is matching case patterns for understanding. Although the compiler verifies that the match is safe (for example, for { x: String <- Option(1) } yield x will not compile), it is still freed from the filtering operation. I do not know why, perhaps, the reason for this, and there is even a small chance that this is a good reason.

You will get a message about filter , because the last compiler in this case. First, he will try to call desugar to call withFilter , and if he does not find withFilter , he will use filter (which, at least in collection library implementations, is generally less efficient in such cases). In the case of WriterT he does not find a single one (since filtering the writer does not make sense in the general case), so he complains about the last one he tried.

The solution is to not use type matching. Write a plain old for { z <- ... } yield z and everything will work fine. In fact, I would advise you never to use font type matching - this is the easiest way to fix reflection problems, ultimately in your code. In this case, the operation will be checked at compile time (at least in obvious cases), but it is still unnecessary and potentially less efficient.

+7
source

Source: https://habr.com/ru/post/1239587/


All Articles