I am writing a Scala class that implements a 2-dimensional matrix of arbitrary objects. I need the class to be more specialized than nested pair of IndexedSeq
objects, but extending a collections class is overkill, so I'm writing my own. In order to return the correct type from methods in my matrix class, I am using the implicit builder idiom, but at runtime I get a "could not find implicit value for parameter" error which I don't understand.
A stripped-down version of my matrix class looks like this.
trait MatrixBuilder[V, M <: Matrix[V]] {
def apply(values: IndexedSeq[IndexedSeq[V]]): M
}
abstract class Matrix[V](values: IndexedSeq[IndexedSeq[V]]) extends Function2[Int, Int, V] {
def apply(row: Int, col: Int): V = values(row)(col)
def set[M <: Matrix[V]](row: Int, col: Int, value: V)(implicit builder: MatrixBuilder[V, M]): M =
builder(values.updated(row, values(row).updated(col, value)))
}
case class IntMatrix(values: IndexedSeq[IndexedSeq[Int]]) extends Matrix[Int](values)
object IntMatrix {
def apply(n: Int) = new IntMatrix(IndexedSeq.fill(n, n)(0))
implicit object IntMatrixBuilder extends MatrixBuilder[Int, IntMatrix] {
def apply(values: IndexedSeq[IndexedSeq[Int]]) = IntMatrix(values)
}
}
I want the set
function to set the specified cell then return a new matrix of the correct type. So I expect IntMatrix(2).set(0,0,5)
to return an IntMatrix
object with zeros in all cells except (0,0), where it should have a 5. Instead I get the following error at runtime.
error: could not find implicit value for parameter builder: MatrixBuilder[Int,M]
IntMatrix(2).set(0,0,5)
What am I doing wrong here?
As pedrofurla notes below, the code does work in the REPL if you first run the line import IntMatrix._
. And looking at the collections documentation, there appear to be similar import statements in source code using builders. I tried adding one to my IntMatrix
class.
case class IntMatrix(values: IndexedSeq[IndexedSeq[Int]]) extends Matrix[Int](values) {
import IntMatrix._
}
But this has no effect. (In fact my IDE IntelliJ flags this as an unused import statement.)
For comparison I copied over the RNA sequence example from the collections documentation linked above verbatim. There the import RNA._
line is not marked as superfluous and all operations return the correct type. If the answer is that I need to add an import IntMatrix._
, I can't figure out where to put it.
IntMatrix(2).set(0,0,5)
call, and reproduce the issue. I'm tempted to think that since IntMatrix isn't parameterized it might not be seen as a subclass of Matrix[Int], and so doesn't fit the definition of your type M required for the implicit builder? I'm not really sure about that though. This was at runtime not compile time? – nairbvSolution
was a typo. It should have beenIntMatrix
. I fixed this. This is a runtime error.IntMatrix
extendsMatrix[Int]
which I think should meet the type signature of the builder. – W.P. McNeillset
. Add this explanation to my answer. – pedrofurla