Search code examples
scalagenericsscala-collections

Scala: Problems creating generic collection


I have two sorted lists, and want to create an iterator which will merge the two lists in sorted oder. I'm new to Scala and especially new with writing generic classes. I get a compile error that I'm unable to figure out.

Here is the code for MergingIterator

class MergingIterator[ElementType <: Ordered[ElementType]] (iterator1: BufferedIterator[ElementType], iterator2: BufferedIterator[ElementType]) extends Iterator[ElementType]{


 override def hasNext: Boolean = {
   iterator1.hasNext || iterator2.hasNext
 }

 override def next(): ElementType = {
   if(!iterator1.hasNext && !iterator2.hasNext){
    throw new IllegalStateException("All iterators empty.  No next element")
   }
   val e1 : Option[ElementType] = if(iterator1.hasNext) Some(iterator1.head) else None
   val e2 : Option[ElementType] = if(iterator2.hasNext) Some(iterator2.head) else None
   if(e1.isDefined && e2.isDefined){
     val e1a = e1.get
     val e2a = e2.get
     if(e1a.equals(e2a) || e1a < e2a){
       iterator1.next()
     }
     else {
       iterator2.next()
     }
   }
   else if (e1.isDefined){
     iterator1.next
   }
   else if (e2.isDefined){
     iterator2.next()
   }
   else{
     throw new Exception("InvalidState.  No elements present")
   }
 }
}

And here is the Unit Test, which is what doesn't compile:

class MergingIteratorTest extends AnyFunSuite {

  test("Both Iterators Empty"){
    runTest(List(), List(), List())
  }

  private def runTest(vals1 : List[ComparableInt], vals2: List[ComparableInt], expected: List[ComparableInt]): Unit ={
    val it1 = vals1.iterator.buffered
    val it2 = vals2.iterator.buffered
    val merging = new MergingIterator[ComparableInt](it1, it2)
    val merged = merging.toList
    assert(expected.equals(merged))
  }

  case class ComparableInt(value: Int) extends Ordered[Int] {
    override def compare(that: Int): Int = value - that
  }

}

However when I try to compile, I get the following errors.

Error:(14, 9) type arguments [MergingIteratorTest.this.ComparableInt] do not conform to class MergingIterator's type parameter bounds [ElementType <: Ordered[ElementType]]
    val merging = new MergingIterator[ComparableInt](it1, it2)
Error:(14, 23) type arguments [MergingIteratorTest.this.ComparableInt] do not conform to class MergingIterator's type parameter bounds [ElementType <: Ordered[ElementType]]
    val merging = new MergingIterator[ComparableInt](it1, it2)

I'm sure it's something stupid that I'm doing wrong, but due to my lack of experience with scala I've been able to figure out what the problem is. Any help here would be appreciated.


Solution

  • You need to make

    case class ComparableInt(value: Int) extends Ordered[ComparableInt] {
        override def compare(that: ComparableInt): Int = value.value - value.value
    }
    

    The issue is in [ElementType <: Ordered[ElementType]] type bounds - you see ElementType should be ordered to itself and your case ComparableInt implements Ordered[Int] and meaning ComparableInt is not Ordered to itself as MergingIterator signature expects.