我试图实现一个简单的设计目标,但是 Scala 类型系统的复杂性让我有些头疼。在比较了 Traversable、Iterator、Iterable、Stream、View 等之后,我的决定是定义一个自定义特征(为了简洁起见,我们称之为Stream
)
- 是非泛型的(我的流在语义上只有一些有意义
Stream[StreamEntry]
,我想避免像这样无意义的类型Stream[Int]
) - 有类似的用法
Iterable
- 所有成员,如
take
,等都drop
应该返回Stream
,而不是基本的Iterable
。
这是我到目前为止所尝试的:
方法一
为了勾勒用例,一个简单的例子(违反了第三个设计目标)是:
case class StreamEntry(data: Double) // just a dummy
trait Stream extends Iterable[StreamEntry] {
val metaInfo: String
}
// example use case
val s = new Stream {
val metaInfo = "something"
val iterator = StreamEntry(1) :: StreamEntry(2) :: StreamEntry(3) :: Nil toIterator
}
val t = s.take(1) // unfortunately, this is no longer a Stream
方法二
第三个要求要求使用模板特征而不是基本特征(我希望这是引用SomeCollection或SomeCollectionLike的标准术语)。这意味着我必须使用IterableLike[StreamEntry, Stream]
which 重新定义表示集合的返回类型,就像Iterable
extendsIterableLike[A, Iterable[A]]
到 return一样Iterable
。我的想法是做几乎相同的事情Iterable
。这将是:
// this is exactly the way `Iterable` is defined, but non-generic
trait Stream extends Traversable[StreamEntry]
with GenIterable[StreamEntry]
with GenericTraversableTemplate[StreamEntry, Stream]
with IterableLike[StreamEntry, Stream] {
...
}
不幸的是,这不能编译,因为Stream
它作为模板参数出现,GenericTraversableTemplate
并且编译器现在需要一个模板参数(正好是一个)Stream
,这是有道理的。
方法 3、4、...
从这里开始,我迷失在类型系统中。由于from和. with GenericTraversableTemplate
_ _newBuilder
GenericTraversableTemplate
GenInterable
Traversable
也许最接近的解决方案如下:
trait Stream extends TraversableLike[StreamEntry, Stream]
with IterableLike[StreamEntry, Stream] {
val metaInfo: String
def seq = this
def newBuilder: scala.collection.mutable.Builder[StreamEntry, Stream] = ???
}
这可以编译,但不幸的是我不知道如何实现 Builder。是否可以为我的非通用特征重用通用生成器?实际上,我虽然可以不使用 Builder,因为我从来没有真正想Stream
从其他集合中构建一个新的。但是目前我在使用这种方法时遇到了一些奇怪的运行时行为,我无法完全理解。例如:
val s = new Stream {
val metaInfo = "something"
val iterator = StreamEntry(1) :: StreamEntry(2) :: StreamEntry(3) :: Nil toIterator
}
// executing the following independently (not in sequence) results in:
s.take(1) // throws: scala.NotImplementedError: an implementation is missing
// seems to require a Builder :(
s.toArray // works
s.toIterator // works
s.toIterable // throws: java.lang.ClassCastException: cannot be cast to scala.collection.Iterable
现在,我对 Scala 类型系统的深度感到有些迷失。我是否仍然在使用最后一种方法的正确轨道上,而 Builder 是否只是这个难题中缺失的部分?
对于非泛型非缓存类型,Builder 实现会是什么样子?一个简单的实现想法+=
是使用一些可变缓冲区,但这首先会非常反对使用迭代器......to
如果我不知道如何构造一个类,我应该如何实现该成员类型?我想所有相关的代码都必须在图书馆的某个地方,我就是无法挖掘出来。