scala - Correct usage of inheritance for wrapper classes -
i trying write scala-wrapper matrix operations, using ejml library. use simplematrix. however, want different classes matrix , vector, example able invert matrix or explicitly state function returns vector, not matrix. currently, having trouble returning concrete classes instead of trait.
i started trait, mlmatrixlike:
trait mlmatrixlike { def data: simplematrix protected def internalmult(implicit that: mlmatrixlike): simplematrix = { data.mult(that.data) } def *(implicit that: mlmatrixlike): mlvector = mlvector(internalmult) }
both matrix class , vector class extending trait:
case class mlmatrix(data: simplematrix) extends mlmatrixlike { def this(rawdata: array[array[double]]) = this(new simplematrix(rawdata)) def apply(row: int, col:int): double = data.get(row, col) def transpose(): mlmatrix = mlmatrix(data.transpose()) def invert(): mlmatrix = mlmatrix(data.invert()) def *(implicit that: mlmatrix): mlmatrix = mlmatrix(internalmult) def *(that: double): mlmatrix = mlmatrix(data.scale(that)) def -(that: mlmatrix): mlmatrix = mlmatrix(data.minus(that.data)) } object mlmatrix { def apply(rawdata: array[array[double]]) = new mlmatrix(rawdata) } case class mlvector(data: simplematrix) extends mlmatrixlike { def this(rawdata: array[double]) = { this(new simplematrix(array(rawdata)).transpose()) } def apply(index: int): double = data.get(index) def transpose(): mlvector = mlvector(data.transpose()) def -(that: mlvector): mlvector = mlvector(data.minus(that.data)) } object mlvector { def apply(rawdata: array[double]) = new mlvector(rawdata) }
to mind, setup not good. define multiply (*) once, since simplematrix-call same , can infer type of parameter "that" whether return type should matrix or vector. define single function in mlmatrixlike along lines of (not working) function:
def *[t <: mlmatrixlike](that :t): t = { new t(data.mult(that.data)) }
of course, not work, since there no such constructor t, fail see, how can similar work. returning mlmatrixlike not correct mind, since way cannot check during compilation if correct type returned.
a similar problem applies transpose, , minus - here return type own class.
thank much!
i'm not sure benefits of wrapping simplematrix
in 2 other classes are. however, solve duplication problem making mlmatrixlike
generic self-type, , defining abstract constructor.
trait mlmatrixlike[self <: mlmatrixlike[self]] { this: self => def data: simplematrix def createnew(data: simplematrix): self def *[t <: mlmatrixlike[t]](that: t): t = that.createnew(data.mult(that.data)) def *(that: double): self = createnew(data.scale(that)) def -(that: self): self = createnew(data.minus(that.data)) def transpose: self = createnew(data.transpose()) } case class mlmatrix(data: simplematrix) extends mlmatrixlike[mlmatrix] { this: mlmatrix => def this(rawdata: array[array[double]]) = this(new simplematrix(rawdata)) override def createnew(data: simplematrix): mlmatrix = mlmatrix(data) def apply(row: int, col: int): double = data.get(row, col) def invert(): mlmatrix = mlmatrix(data.invert()) } object mlmatrix { def apply(rawdata: array[array[double]]) = new mlmatrix(rawdata) } case class mlvector(data: simplematrix) extends mlmatrixlike[mlvector] { this: mlvector => def this(rawdata: array[double]) = { this(new simplematrix(array(rawdata)).transpose()) } override def createnew(data: simplematrix): mlvector = mlvector(data) def apply(index: int): double = data.get(index) } object mlvector { def apply(rawdata: array[double]) = new mlvector(rawdata) }
by way, note, column vector times row vector matrix, signature of multiplication should not return type of that
. however, based on static information (you need know dimensions of both arguments) cannot tell whether multiplication returns vector or matrix, may aswell return mlmatrixlike
.
Comments
Post a Comment