Scalaz:过滤器在| @ |中起什么作用?
我们在Futures上使用了WriterT monad转换器希望从异步应用程序中获取更多有组织的日志,但是我们遇到了一些麻烦.
如果我编译下面的应用程序,我会收到以下错误.请注意,这不是关于withFilter的警告.
为什么| @ |需要在这里过滤? Scalaz是否为此案例提供了隐式转换? import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future import scalaz._ import Scalaz._ object Failure extends App { type LoggedT[F[_],A] = WriterT[F,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) } } Scala版本发生错误:2.11.7和Scalaz版本:7.2.0 解决方法
使用反射库的reify来查看desugaring期间发生的事情通常很方便(这是我唯一一次建议从scala.reflect.runtime导入任何东西,甚至在这种情况下只在开发期间的REPL中):
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))) 问题是for-comprehension中的类型案例模式匹配.即使编译器将验证匹配是否安全(例如,对于{x:String< - Option(1)},yield x将无法编译),它仍然可以用于过滤操作.我不确定为什么 - 这可能是有原因的,而且这是一个很好的理由. 您收到有关过滤器的消息,因为在这种情况下,这是编译器的最后手段.首先,它会尝试去调用withFilter,如果找不到withFilter,它将使用过滤器(至少在集合库的实现中,这样的情况通常效率较低).在WriterT的情况下,它既没有找到(因为过滤作者在一般情况下没有意义),所以它抱怨它尝试的最后一个. 解决方案就是不使用类型大小写匹配.为{z< - ...} yield z写一个简单的旧的东西,一切都会正常工作.事实上,I’d suggest not ever using type-case matching-这是运行时反射相关问题最终出现在代码中的最偷偷摸摸的方式.在这种情况下,将在编译时检查操作(至少在明显的情况下),但它仍然是不必要的,可能效率较低. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |