在Traversable视图上执行foldLeft时,在Scala中键入方差错误 [英] Type variance error in Scala when doing a foldLeft over Traversable views
问题描述
我尝试使用 foldLeft
运算符在Scala中连接一系列 Traversable
视图,我不明白。
我可以使用 reduce
来连接 Traversable
的视图。
val xs = List(1,2,3,4)。 map(TraversableView [Int,Traversable [_]],b:TraversableView [Int,Traversable [_]])=> a ++ b)// TraversableView [Int ,Traversable [_]]
// xs.force返回Traversable [Int] = List(1,2,3,4)
(注意,我必须在 reduce
参数上写类型注释: reduce )
不编译,我不明白为什么,也将感谢这种解释。)
我也可以打破列为头部和尾部,并将它们连接起来。
import collection.TraversableView
val ns = List ,2,3,4)
val h = Traversable(ns.head).view
val t = ns.tail.map(Traversable(_)。view).reduce((a:TraversableView [ Int,Traversable [_]],b:TraversableView [Int,Traversable [_]])=> a ++ b)
val xs = h ++ t // TraversableView [Int,Traversable [_]]
// xs.force返回Traversable [Int] = List(1,2,3, 4)
但是如果我尝试用 foldLeft
我得到类型方差错误。
import collection.TraversableView
/ pre>
val ns = List ,2,3,4)
val h = Traversable(ns.head).view
val t = ns.tail.map(Traversable(_)。view)
val xs = h /:t)((a:TraversableView [Int,Traversable [_]],b:TraversableView [Int,Traversable [_]])=> a ++ b)
< console&错误:类型不匹配;
found:scala.collection.TraversableView [Int,Traversable [_]]
必需:java.lang.Object with scala.collection.TraversableView [Int,Traversable [Int]]
/:t)((a:TraversableView [Int,Traversable [_]],b:TraversableView [Int,Traversable [_]])=> a ++ b)
我怀疑问题与
Traversable [_]
中的存在类型有关,不知道我做错了什么。我试过在上面的表达式中的各种类型签名没有效果。从Stackoverflow的其他问题来看,对foldLeft
的输入有些棘手,但是我找不到解决这个问题的方法。
为了比较,使用
Stream
的同样的算法不用担心。val xs =(1#:: Stream.empty /:List(2,3,4).map(_#:: Stream.empty))(_ ++ _)
// xs.force返回Stream [Int] = Stream(1,2,3,4)
上面是我想要做的,除了我想使用视图而不是
Stream
,因为我不需要记住我的所有结果。
这可能看起来像一个奇怪的请求。 我想这样做是因为执行
foldLeft
overTraversable
实现延迟深度优先搜索的有效方法。 / p>
解决方案视图不保留
++ 操作。我很确定这是一个错误。你可以通过转换来修复它:
val xs = List(1,2,3,4).map(Traversable )。视图)。
reduce((a,b)=>(a ++ b).asInstanceOf [TraversableView [Int,Traversable [Int]]))
在折叠的情况下:
val xs = ).view /:List(2,3,4).map(x => Traversable(x).view)){(l,r)=&
(l ++ r).asInstanceOf [TraversableView [Int,Traversable [Int]]]
}
但要小心!一旦你开始显式转换,你的类型安全性就会下降(也就是说你不会犯错误)。
我猜这是一个症状视图没有被大量使用。我通常尝试使用
Iterator
如果在所有可能,而不是各种不同的视图。I am trying concatenate a series of
Traversable
views in Scala using afoldLeft
operator and am hitting type variance errors that I don't understand.I can use
reduce
to concatenate a list ofTraversable
views like so.val xs = List(1,2,3,4).map(Traversable(_).view).reduce((a: TraversableView[Int, Traversable[_]], b: TraversableView[Int, Traversable[_]]) => a ++ b) // TraversableView[Int,Traversable[_]] // xs.force returns Traversable[Int] = List(1, 2, 3, 4)
(Note that I have to write the type annotation on the
reduce
arguments:reduce(_ ++ _)
does not compile. I don't understand why and would be grateful for an explanation of this too.)I can also break the list up into a head and a tail and concatenate them.
import collection.TraversableView val ns = List(1,2,3,4) val h = Traversable(ns.head).view val t = ns.tail.map(Traversable(_).view).reduce((a: TraversableView[Int, Traversable[_]], b: TraversableView[Int, Traversable[_]]) => a ++ b) val xs = h ++ t // TraversableView[Int,Traversable[_]] // xs.force returns Traversable[Int] = List(1, 2, 3, 4)
But if I try to do the same thing with a
foldLeft
I get type variance errors.import collection.TraversableView val ns = List(1,2,3,4) val h = Traversable(ns.head).view val t = ns.tail.map(Traversable(_).view) val xs = (h /: t)((a: TraversableView[Int, Traversable[_]], b: TraversableView[Int, Traversable[_]]) => a ++ b) <console>:14: error: type mismatch; found : scala.collection.TraversableView[Int,Traversable[_]] required: java.lang.Object with scala.collection.TraversableView[Int,Traversable[Int]] (h /: t)((a: TraversableView[Int, Traversable[_]], b: TraversableView[Int, Traversable[_]]) => a ++ b)
I suspect the issue has to do with the existential type in
Traversable[_]
, but I can't figure out what exactly I'm doing wrong. I've tried various type signatures in the above expression to no avail. Judging from other questions on Stackoverflow, there is something tricky about the typing offoldLeft
, but I couldn't find one that addresses this issue.For comparison, the same algorithm with
Stream
works without a hitch.val xs = (1 #:: Stream.empty /: List(2,3,4).map(_ #:: Stream.empty))(_ ++ _) // xs.force returns Stream[Int] = Stream(1, 2, 3, 4)
The above is what I want to do, except I want to use a view instead of
Stream
because I don't need to memoize all my results.This might seem like an odd request. The reason I want to do things this way is because performing
foldLeft
overTraversable
views provides an efficient way to implement a lazy depth first search.解决方案Views don't maintain the identity of the contained element across
++
operations. I'm pretty sure that this is a bug. You can fix it by casting:val xs = List(1,2,3,4).map(Traversable(_).view). reduce((a,b) => (a ++ b).asInstanceOf[TraversableView[Int,Traversable[Int]]])
In the fold case also:
val xs = (Traversable(1).view /: List(2,3,4).map(x => Traversable(x).view)){ (l,r) => (l ++ r).asInstanceOf[TraversableView[Int,Traversable[Int]]] }
Be careful, though! Once you start explicitly casting, your type safety goes way down (i.e. it is up to you to not make a mistake).
I'd guess this is a symptom of views not being very heavily used. I generally try to use
Iterator
if at all possible rather than various different views.这篇关于在Traversable视图上执行foldLeft时,在Scala中键入方差错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!