为什么Scala为“for”表达式选择类型“Product”,涉及到任何一个
如果我使用Option创建一个具有值定义的理解,它的工作原理如下:
scala> for (a <- Some(4); b <- Some(5); val p = a * b) yield p res0: Option[Int] = Some(20) 做同样的事情,如果我没有价值定义,可以工作: scala> for (a <- Right(4).right; b <- Right(5).right) yield a * b res1: Either[Nothing,Int] = Right(20) 但是,如果我使用了值定义,scala似乎推断了错误的容器类型,以便理解: scala> for (a <- Right(4).right; b <- Right(5).right; val p = a * b) yield p <console>:8: error: value map is not a member of Product with Serializable with Either[Nothing,(Int,Int)] for (a <- Right(4).right; b <- Right(5).right; val p = a * b) yield p ^ 为什么这样做?这种行为有什么方法可用? 解决方法
问题来自val p = a * b
如果你写的更简单 for(a< - Right(4).right; b< - Right(5).right)产生一个* b 它编译,你得到正确的结果. 你的问题有两个原因 首先,两个投影图和flatMap都不具有通常的签名,即在通用类M [A],(A => B)=>中定义的例程map和flatMap. M [B]和(A => M [B])=> M [B]. M [A]程序定义为[A,B] .RightProjection,但在结果和参数中,我们有[A,B]而不是投影. 第二,理解中的方法val p = a * b被翻译. Scala参考,6.19 p 90:
(p,p′) <- for(x@p<-e) yield {val x′@p′ = e′; (x,x′)} 让我们简化一下代码,放一个< - .此外,b和p更名为p和pp更接近重写规则,pp为p'.一个应该在范围内 for((p,pp) <- for(x@p <- Right(5).right) yield{val xx@pp = a*p; (x,xx)}) yield pp 内部版本被重写为简单的地图 for((p,pp) <- Right(5).right.map{case x@p => val xx@pp = a*p; (x,xx)}) yield pp 这是问题. Right(5).right.map(…)类型是[Nothing,Int)],不是我们想要的Either.RightProjection [Nothing,Int)].它在外部不工作(它也转换为地图也没有地图方法,它只在投影上定义. 如果仔细观察你的错误信息,它就这么说,即使它提到了Product和Serializable,它说它是一个[Nothing,也没有定义地图.对(Int,Int)直接来自重写规则. 理解的目的是在尊重正确的签名时工作得很好.随着两个投影(也有其优点)的诀窍,我们得到这个问题. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |