I am trying to write a scala-wrapper for matrix operations, using the ejml library. Basically I just use SimpleMatrix. However, I want different classes for matrix and vector, for example to only be able to invert a matrix or to explicitly state that a function returns a vector, not a matrix. Currently, I am having trouble returning the concrete classes instead of the trait.
I started with a 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 my matrix class and my vector class are extending the 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 my mind, this setup is not very good. I would like to define multiply (*) only once, since the SimpleMatrix-call is always the same and I can infer from the type of the parameter "that" whether the return type should be a matrix or a vector. Thus I would like to define a single function in MLMatrixLike along the lines of this (not working) function:
def *[T <: MLMatrixLike](that :T): T = {
new T(data.mult(that.data))
}
Of course, this does not work, since there is no such constructor T, but currently I fail to see, how I can get something similar to work. Returning MLMatrixLike is not correct to my mind, since that way I cannot check during compilation if the correct type is returned.
A similar problem applies to transpose, and minus - here the return type is always the own class.
Thank you very much!
I'm not sure what the benefits of wrapping SimpleMatrix in two other classes are. However, you could solve the duplication problem by making MLMatrixLike generic with its self-type, and defining an 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 the way, note, that a column vector times a row vector is a matrix, so the signature of the multiplication should probably not return the type of that. However, based on static information (you need to know the dimensions of both arguments) you cannot tell whether a multiplication returns a vector or a matrix, so you may aswell just return a MLMatrixLike.
Related
Let's say I have a class called A:
class A(i: Int) {
//private def to initialize a calculated value
def maintainedValue : Int = calculatedValue
def double : A = new A(maintainedValue * 2)
def combine(other: A) : A = new A(maintainedValue + other.maintainedValue)
def addAmt(amt : Int) : A = new A(maintainedValue + amt)
// Many many more methods
}
I want to define a class B that extends class A such that it's methods, almost all of which have similar logic, return an object of class B:
class B(i: Int) extends A(i) {
//private def to initialize a differently calculated value
def maintainedValue : Int = diffCalculatedValue
//Change all other methods to return type B without override???
}
Is it possible to do this without overriding all the methods?
Is there a simple way to instantiate these new instances with a variable/dynamic class?
Perhaps there is a more elegant way to do this?
One solution, and the simplest one in my opinion, is to change class A to have a structure such that a single method handles object creation:
def create(i: Int): TYPE = new B(i)
And just use an implicit method in class B to handle casting when calling the unaltered methods:
private implicit def convert(a: A): B = new B(a.maintainedValue)
Short and sweet, though I'm curious how efficient and/or scale-able this solution is.
How about having base trait with common logic and two implementation?
object App extends App {
println(A(1).double)
println(B(1).double)
}
trait A {
type TYPE
def create(i: Int): TYPE
def maintainedValue: Int
def double: TYPE = create(maintainedValue * 2)
def addAmt(amt: Int): TYPE = create(maintainedValue + amt)
}
trait B extends A {
}
object A {
def apply(i: Int) = new AImpl(i)
case class AImpl(i: Int) extends A {
override type TYPE = A
override def create(i: Int) = A(i)
override def maintainedValue: Int = 2
}
}
object B {
def apply(i: Int): B = new BImpl(i)
case class BImpl(i: Int) extends B {
override type TYPE = B
override def create(i: Int): TYPE = B(i)
override def maintainedValue: Int = 1
}
}
This works
trait SomeTrait {
type T
def write2( s: String): T
}
case class C() extends SomeTrait {
type T = String
override def write2(s:String): T = s }
But this does not
trait SomeTrait {
def write2[T]( s: String): T
}
case class C() extends SomeTrait {
override def write2(s: String): String =s }
To my reasoning, they ..seem similar. Why specifically does the compiler give a "method does not override anything" error? IS there a way of making this work?
If you use this definition:
trait T {
def write2[T]( s: String): T
}
Consider some client using this trait. For example:
def doSomething(t: T): Unit = {
val s: String = t.write2[String]("hello")
val n: Int = t.write2[Int]("world")
val d: Double = t.write2[Double]("!")
println(s + n.toString + d.toString)
}
I don't know what the values of s, n, and d would be, but in theory that would be a perfectly valid usage of the trait, from the compiler's perspective. So in order to truly override that write2[T] method, you would have to provide valid behavior for all possible types T.
Compare that to:
trait T2 {
type T
def write2( s: String): T
}
Or even:
trait T3[T] {
def write2(s: String): T
}
Then when callers use it:
def doSomething(t: T2): Unit = {
val x = t.write2("hello") // always returns type t.T
}
def doSomething[T](t: T3[T]): Unit = {
val x = t.write2("hello") // always returns type T
}
There's only one possible type that can be returned, once you have a specific instance of that trait. So to override that method, you need only override the behavior for that one type.
Your trait definition in the second snippet does not mean that implementations of it must have a method write2 for some type T, but that it must have a method write2 which takes a type parameter T.
That means that, if you have a value v: SomeTrait, you should be able to do
val stringed: String = v.method2[String]("foo")
val inted: Int = v.method2[Int]("foo")
This compiles:
trait T {
def write2[T]( s: String): T
}
case class C() extends T {
override def write2[T](s: String): T =s.asInstanceOf[T]
}
write2 returns a T, not a String (hence the reason why your second override does not work and the necessity in the code above for the ugly cast)
I've recently started learning Scala's implicit "magic" and I'm having troubles with implicit Scala objects. I've tried all the possible variants but nothing seems to work.
Lets assume I have a class like this with some solve() function. It should return 2 Float values if the input a, b were Float. Otherwise it should return another type values:
class Solver[T](val a: T, val b: T) {
def solve[A](implicit num: customNumeric[T]): Option[(T, T)] = {
Option(
num.f(num.g(a)),
num.f(num.g(b)))
}
}
Let's assume another-type-value is an object of class like this:
class MyClass[T] (x: T, y: T)(implicit num: customNumeric[T]) {
val field : T = num.f(x)
}
And let's also assume that I dont have the functions I need in basic Scala Numeric so I should make my own custom numeric.
Here is what I've done:
I've made an abstract class for my own customNumeric with my methods f() and g() and couple of implicit objects that extend my customNumeric for some value types (Int, Float for example) and implemented method in them:
abstract class customNumeric[T] {
def f(x: T): T
def g(x: T): T
}
object customNumeric {
implicit object IntIsCustomNumeric extends customNumeric[MyClass[Int]] {
def f(x: MyClass[Int]) = new MyClass[Int](x.field + 5)
def g(x: MyClass[Int]) = new MyClass[Int](x.field - 5)
}
implicit object FloatIsCustomNumeric extends customNumeric[Float] {
def f(x: Float): Float = x + 3
def g(x: Float): Float = x - 3
}
}
In my opinion Solver's solve() should use implicit customNumeric object to get implementations for methods referenced inside solve() based upon type of the Solver's input values.
But this doesn't work as compiler says:
could not find implicit value for parameter num: customNumeric[Int]
def f...
It also complains because of not enough arguments for constructor MyClass at the same line.
I've already tried making companion object to cast Int to MyClass:
object Fraction {
implicit def int2MyClass(x: Int): MyClass[Int] = new MyClass[Int](x, 1)
}
But that also doen't seem to work. And I've tried to make another implicit object to implement methods I use in customNumeric[MyClass[Int]].
Do you have any ideas? Thanks in advance!
The problem is that you're trying to define the implicit objects with classes that themselves require that same implicit object.
Meaning, this:
class MyClass[T] (x: T, y: T)(implicit num: CustomNumeric[T])
Requires an existence of an implicit CustomNumeric[T]. You cannot define IntIsCustomNumeric using that type:
implicit object IntIsCustomNumeric extends customNumeric[MyClass[Int]]
When you implement IntIsCustomNumeric, you need to implement it for type Int, not for type MyClass[Int]. When you do that, i.e:
object CustomNumeric {
implicit object IntIsCustomNumeric extends CustomNumeric[Int] {
override def f(x: Int): Int = x
override def g(x: Int): Int = x
}
}
Now, you can create an Solver[Int] which takes an implicit CustomNumeric[Int]:
def main(args: Array[String]): Unit = {
import CustomNumeric._
val solver = new Solver[Int](1, 2)
println(solver.solve)
}
Now, it's also easier to create an implicit conversion from an Int type to something that creates a MyClass[Int]:
implicit object MyClassIsCustomNumeric extends CustomNumeric[MyClass[Int]] {
override def f(x: MyClass[Int]): MyClass[Int] = new MyClass[Int](x.field + 5)
override def g(x: MyClass[Int]): MyClass[Int] = new MyClass[Int](x.field + 3)
}
implicit def intToMyClass(i: Int) = new MyClass[Int](i)
What do you think about this
object customNumeric {
implicit object IntIsCustomNumeric extends customNumeric[Int] {
def f(x: Int): Int = x + 3
def g(x: Int): Int = x - 3
}
implicit object FloatIsCustomNumeric extends customNumeric[Float] {
def f(x: Float): Float = x + 3
def g(x: Float): Float = x - 3
}
implicit def int2MyClass(x: Int): MyClass[Int] = new MyClass[Int](x, 1)
implicit object cn extends customNumeric[MyClass[Int]] {
def f(x: MyClass[Int]) = x.field + 5
def g(x: MyClass[Int]) = x.field - 5
}
}
I have a trait and a case class implementing it. One of the features of the trait that the implementations override is a default value. I can't find a good way to access this default value from a class that is parametrized by a specific implementation of that trait.
This is minimal code, so it doesn't really demonstrate the motivation anymore, but it does demonstrate the error:
import scala.language.implicitConversions
trait Distance[T] {
val Zero: T
def +( that: T ): T
}
case class DoubleDistance( val v: Double ) extends Distance[DoubleDistance] {
val Zero = DoubleDistance( 0.0 )
def +( that: DoubleDistance ) = DoubleDistance( v + that.v )
}
object DistanceImplicits {
implicit def DoubleToDistance( v: Double ) = new DoubleDistance( v )
}
class User[T<:Distance[T]] {
val default: T = T.Zero // This line gives me a compilation error
}
The error I get is
not found: value T
When I needed to construct an Array[T] inside my User class I could get that to work by adding implicit typetag:ClassTag[T] to my arguments, but that doesn't seem to have any effect here.
First, why this doesn't work: consider a different implementation of Distance.
case class DoubleDistance1(val v: Double) extends Distance[DoubleDistance1] {
val Zero = this
def +(that: DoubleDistance1) = ??? // doesn't matter
}
What would you expect DoubleDistance1.Zero to mean? You can make it work using a "type class":
trait DistanceOps[T] {
val zero: T
def add(d1: T, d2: T): T
}
// just to let you write distance1 + distance2
implicit class RichDistance[T](d: T)(implicit ops: DistanceOps[T]) {
def +(other: T) = ops.add(d, other)
}
case class DoubleDistance(v: Double)
object DoubleDistance {
implicit object DoubleDistanceOps extends DistanceOps[DoubleDistance] {
val zero = DoubleDistance(0.0)
def add(d1: DoubleDistance, d2: DoubleDistance) = DoubleDistance(d1.v + d2.v)
}
}
// how to use
class User[T](implicit ops: DistanceOps[T]) {
val default: T = ops.zero
}
This looks like a classic use case for the type class pattern. Rather than associating an instance of the Distance trait with each value of interest, you associate one with each type of interest:
trait Distance[T] {
val Zero: T
def +( a: T, b: T ): T
}
implicit object DoubleDistance extends Distance[Double] {
val Zero = 0.0
def +( a: Double, b: Double ) = a + b
}
class User[T : Distance] {
val default: T = implicitly[Distance[T]].Zero
}
Where is that Zero supposed to come from? Are you looking to do something like this?
class User[T<:Distance[T]] {
self:Distance[T] =>
val default: T = Zero
}
In short, I want to declare a trait like this:
trait Test {
def test(amount: Int): A[Int] // where A must be a Monad
}
so that I can use it without knowing what monad that A is, like:
class Usecase {
def someFun(t: Test) = for { i <- t.test(3) } yield i+1
}
more details...
essentially, I want to do something like this:
class MonadResultA extends SomeUnknownType {
// the base function
def test(s: String): Option[Int] = Some(3)
}
class MonadResultB(a: MonadResultA) extends SomeUnknownType {
// added a layer of Writer on top of base function
def test(s: String): WriterT[Option, String, Int] = WriterT.put(a.test(s))("the log")
}
class Process {
def work(x: SomeUnknownType) {
for {
i <- x.test("key")
} yield i+1
}
}
I wanted to be able to pass any instances of MonadResultA or MonadResultB without making any changes to the function work.
The missing piece is that SomeUnknowType, which I guess should have a test like below to make the work function compiles.
trait SomeUnknowType {
def test(s: String): T[Int] // where T must be some Monad
}
As I've said, I'm still learning this monad thing... if you find my code is not the right way to do it, you're more than welcomed to point it out~
thanks a lot~~
Assuming you have a type class called Monad you can just write
def test[A:Monad](amount: Int): A[Int]
The compiler will require that there is an implicit of type Monad[A] in scope when test is called.
EDIT:
I'm still not sure what you're looking for, but you could package up a monad value with its corresponding type class in a trait like this:
//trait that holds value and monad
trait ValueWithMonad[E] {
type A[+E]
type M <: Monad[A]
val v:A[E]
val m:M
}
object M {
//example implementation of test method
def test(amount:Int):ValueWithMonad[Int] = new ValueWithMonad[Int] {
type A[+E] = Option[E]
type M = Monad[Option]
override val v = Option(amount)
override val m = OptionMonad
}
//test can now be used like this
def t {
val vwm = test(1)
vwm.m.bind(vwm.v, (x:Int) => {
println(x)
vwm.m.ret(x)
})
}
}
trait Monad[A[_]] {
def bind[E,E2](m:A[E], f:E=>A[E2]):A[E2]
def ret[E](e:E):A[E]
}
object OptionMonad extends Monad[Option] {
override def bind[E,E2](m:Option[E], f:E=>Option[E2]) = m.flatMap(f)
override def ret[E](e:E) = Some(e)
}