在Traversable视图上执行foldLeft时,在Scala中键入方差错误 [英] Type variance error in Scala when doing a foldLeft over Traversable views

查看:232
本文介绍了在Traversable视图上执行foldLeft时,在Scala中键入方差错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试使用 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 
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)
/ pre>

我怀疑问题与 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 over Traversable 实现延迟深度优先搜索的有效方法。 / 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 a foldLeft operator and am hitting type variance errors that I don't understand.

I can use reduce to concatenate a list of Traversable 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 of foldLeft, 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 over Traversable 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆