Compile-time check for vector dimension - scala

I am implementing some lightweight mathematical vectors in scala. I would like to use the type system to check vector compatibility at compile time. For example, trying to add a vector of dimension 2 to another vector of dimension 3 should result in a compile error.
So far, I defined dimensions as case classes:
sealed trait Dim
case class One() extends Dim
case class Two() extends Dim
case class Three() extends Dim
case class Four() extends Dim
case class Five() extends Dim
And here is the vectors definition:
class Vec[D <: Dim](val values: Vector[Double]) {
def apply(i: Int) = values(i)
def *(k: Double) = new Vec[D]( values.map(_*k) )
def +(that: Vec[D]) = {
val newValues = ( values zip that.values ) map {
pair => pair._1 + pair._2
}
new Vec[D](newValues)
}
override lazy val toString = "Vec(" + values.mkString(", ") + ")"
}
This solution works well, however I have two concerns:
How can I add a dimension():Int method that returns the dimension (ie. 3 for a Vec[Three])?
How can I handle higher dimensions without declaring all the needed case classes in advance ?
PS: I know there are nice existing mathematical vector libs, I am just trying to improve my scala understanding.

My suggestions:
Peano Numbers by Apocalysp (link to part a, other parts follow)
Church Numerals by Jim McBeath

I's suggest something like this:
sealed abstract class Dim(val dimension:Int)
object Dim {
class One extends Dim(1)
class Two extends Dim(2)
class Three extends Dim(3)
implicit object One extends One
implicit object Two extends Two
implicit object Three extends Three
}
case class Vec[D <: Dim](values: Vector[Double])(implicit dim:D) {
require(values.size == dim.dimension)
def apply(i: Int) = values(i)
def *(k: Double) = Vec[D]( values.map(_*k) )
def +(that: Vec[D]) = Vec[D](
( values zip that.values ) map {
pair => pair._1 + pair._2
})
override lazy val toString = values.mkString("Vec(",", ",")")
}
Of course you can get only a runtime check on the vector length that way, but as others pointed already out you need something like Church numerals or other typelevel programming techniques to achieve compile time checks.
import Dim._
val a = Vec[Two](Vector(1.0,2.0))
val b = Vec[Two](Vector(1.0,3.0))
println(a + b)
//--> Vec(2.0, 5.0)
val c = Vec[Three](Vector(1.0,3.0))
//--> Exception in thread "main" java.lang.ExceptionInInitializerError
//--> at scalatest.vecTest.main(vecTest.scala)
//--> Caused by: java.lang.IllegalArgumentException: requirement failed

If you don't wish to go down the Peano route, you could always have your Vec be constructed with a D and then use the instance for determine the dimension via the Dim companion object. For instance:
object Dim {
def dimensionOf(d : Dim) = d match {
case One => 1
case Two => 2
case Three => 3
}
}
sealed trait Dim
I think for choice, you should be using case objects rather than case classes:
case object One extends Dim
case object Two extends Dim
Then on your vector, you might have to actually store the Dim:
object Vec {
def vec1 = new Vec[One](One)
def vec2 = new Vec[Two](Two)
def vec3 = new Vec[Three](Three)
}
class Vec[D <: Dim](d : D) {
def dimension : Int = Dim dimensionOf d
//etc

Related

Scala change parameters of function defined in trait

Because I didn't find a solution to my problem anywhere, I think I might be thinking into a very wrong direction.
Here's my problem:
I have a trait A and another trait B and companion objects AB1, AB2, AB3 and so on. The singleton objects extend trait A and the classes extend trait B. Many objects of those classes are in a list.
On these objects I want to use functions defined in the corresponding singleton object which take objects of the same class as the singleton object is.
This an example for the traits:
trait A {
def compare(firstB: B, secondB: B) : Int
}
trait B {}
And the companion objects:
class AB1(val variable: Int) extends B {}
object AB1 extends A {
def apply(list: List[Int]): Option[AB1] = {
if(list.foldLeft(0)(_ + _) < 10 && list.nonEmpty)
some(new AB1(list.head))
else
null
}
override def compare(ab11: AB1, ab12: AB1): Int = {
if(ab11 > ab12)
1
else if(ab11 > ab12)
-1
else
0
}
}
and
class AB2(val variable1: Int, val variable2: Int) extends B {}
object AB2 extends A {
def apply(list: List[Int]): Option[AB1] = {
if(list.foldLeft(0)(_ + _) < 20 && list.length >= 2)
some(new AB1(list.head, list.tail.head))
else
null
}
override def compare(ab21: AB2, ab22: AB2): Int = {
if(ab11 > ab12)
10
else if(ab11 > ab12)
-10
else
0
}
}
So I've already filtered the some objects and put the "real" objects into a list, let's call it bList. On every element of the list I want to call the compare function.
I think it would look something like this:
val bList: List[B]
val a = getA(bList.head) // getA should be a function that returns the companion object of a class
a.compare(bList.head, bList.tail.head)
On my way I encountered two problems:
b.getClass does not equal AB1.getClass when b is an object the class AB1. But this is not my main problem. I found a solution using String comparison, which really is not pretty, but for now, it works.
The compare function has to be defined in the trait, because otherwise it can't be casted on any singleton object that extends trait A. But I find no way to define the function with parameters of a variable type.
I really hope you can help me with this problem!
EDIT: Now I see that I've forgotten to mention something:
I think that I have to go a bit deeper into what I am trying to do to make you understand my problem:
I have a List[List[C]]. A List of those C's may be capable of creating an AB1 object with it but maybe AB2, or maybe AB3 and so on. So I have
val c: List[C] = (C1, C2, C4)
val aList: List[A] = (AB1, AB2, AB3, ...)
val bestB: B = (for{
element <- aList
} yield element (c)).flatten.head // Because the List aList is ordered: AB1 is the best case, AB2 the second best and so on.
I do that for every List[C] out of the List[List[C]]. So in the end I may have a List[B] = (AB3, AB1, AB2, AB1) (for example). From this list I want to get the "best" Bs according to the order of aList at first - then i get List[B] = (AB1, AB1). These two AB1's I want to compare and then put the "better" Element (according to the compare function of the corresponding object) or both into a new list. This is want I want to accomplish.
To be honest, I'm still confused with what is your root problem. But I will try to answer what I understood.
First, if you want to change the type of the arguments when overriding a function from a trait. Then, the answer is you can't! - Because that would break the Liskov Substitution Principle.
But you can achieve what you want with a Type Class .
trait B {}
trait BComparator[Bi <: B] {
def compare(firstB: Bi, secondB: Bi): Int
}
Now if you want a way to dynamically obtain the right instance of the BComparator for your sub-classes you could make those instances as implicit values in their companion objects.
class B1 extends B {}
object B1 {
implicit val B1Comparator: BComparator[B1] = new BComparator[B1] {
override def compare(firstB: B1, secondB: B2): Int = ???
}
}
Now, given b11 and b12 as instances of B1 you could just write
implicitly[BComparator[B1]].compare(b11, b12)
I think you need to use implicit Comparator:
trait B
case class AB1(variable: Int) extends B
case class AB2(variable1: Int, variable2: Int) extends B
implicit object AB1Comparator extends Comparator[AB1] {
override def compare(o1: AB1, o2: AB1): Int = java.lang.Integer.compare(o1.variable, o2.variable)
}
implicit object AB2Comparator extends Comparator[AB2] {
override def compare(o1: AB2, o2: AB2): Int = java.lang.Integer.compare(o1.variable1, o2.variable1) match {
case 0 => java.lang.Integer.compare(o1.variable2, o2.variable2)
case other => other
}
}
def compare[A](obj1: A, obj2: A)(implicit comparator: Comparator[A]) = {
comparator.compare(obj1, obj2)
}
val ab1List = List(AB1(1), AB1(2), AB1(3))
val ab1Compare = compare(ab1List.head, ab1List.tail.head)
val ab2List = List(AB2(1, 1), AB2(1, 1), AB2(1, 3))
val ab2Compare = compare(ab2List.head, ab2List.tail.head)
Or if you want to sort list you should use Ordering:
trait B
case class AB1(variable: Int) extends B
implicit object AB1Ordering extends Ordering[AB1] {
override def compare(o1: AB1, o2: AB1): Int = java.lang.Integer.compare(o1.variable, o2.variable)
}
val ab1List = List(AB1(1), AB1(2), AB1(3))
val ab1ListSorted = ab1List.sorted

A more functional way to write this?

I was thinking about something, I wrote this trait with two classes extending it and another class that may contain them:
sealed trait MainObj
case object subObj1 extends mainObj
case Object subObj2 extends mainObj
case class AnotherClass(val mo: Option[MainObj], val amount: Int)
Now let's say I wanted to write a function that added the amounts in twoAnotherClass objects but only if the optional MainObj inside each of them were the same type. Like only add if both are subObj1.
So I could do something like this:
def add(one: AnotherClass, two: AnotherClass): AnotherClass = one. mo, two.mo match {
case (Some(x), Some(y)) if i and x are the same class => return a `AnotherClass` with the two integers added from `one` and `two`
etc..
I wondered whether there was another way of doing this? I don't know whether this is a "functional" way of doing it or whether there is a less verbose way?
I ask because essentially I could write some more methods like subtract, multiply, etc ... and I have some very common code.
I could extract that common code and write a function that simply takes two of the subObjs and an operation and then apply that operation on the two objects, but that only abstracts out the common operation, could the main pattern matching part be written differently that may be considered more concise(for lack of a better word)?
Just add the 'add' method to the case class :
sealed trait MainObj
case object SubObj1 extends MainObj
case object SubObj2 extends MainObj
case class AnotherClass(val mo: Option[MainObj], val amount: Int){
def add(that:AnotherClass):AnotherClass = {
if (that.mo == this.mo)
this.copy(amount = this.amount + 1)
else
this
}
}
val x = AnotherClass(Some(SubObj1), 1)
val y = AnotherClass(Some(SubObj1), 1)
val z = AnotherClass(Some(SubObj2), 1)
scala> x add y
res5: AnotherClass = AnotherClass(Some(SubObj1),2)
scala> x add z
res6: AnotherClass = AnotherClass(Some(SubObj1),1)
scala> val l = List(x,y,z)
l.reduce ( _ add _)
res7: AnotherClass = AnotherClass(Some(SubObj1),2)
val mo = two.mo
one match {
case AnoterClass(`mo`, am) =>
one.copy(amount = am + two.amount)
case _ => ???
}

Scala: Convert nested value classes to Vector

I have some type safe case classes that i want to turn into a vector:
case class Bdrms(underlying: Double) extends AnyVal
object Bdrms {
implicit def toBdrm(x: Double): Bdrms = Bdrms(x)
}
case class Bath(underlying: Double) extends AnyVal
object Bath {
implicit def toBath(x: Double): Bath = Bath(x)
}
// same pattern for many (20-30) other variables. sq ft, price, etc.
// and a parent case class
case class RealEstateDataPoint(bdrm: Bdrm, bath: Bath, sqft: Sqft,//)
one service needs to use these Doubles in the form of a Vector. if value classes were not used, i.e. if we just had
case class RealEstateDatePoint(bdrm: Double, bath: Double...)
then something like the following works to iterate over the fields to create a vector:
def toVector(dataCC: RealEstateDataPoint): Vector[Double] = {
val m = dataCC.productArity
val vector = Vector(m)
for (i<-0 until m) {
vector(i) = dataCC.productElement(i).asInstanceOf[Double]
}
vector
}
But of course, the asInstanceOf type cast wont work with our value classes. Is there an idiomatic/efficient way to make the conversion to a vector?
You can use structural typing:
dataCC.productIterator.map {
case h:{ val underlying: Double } => h.underlying
}.toVector
You might also consider making all the case classes inherit some trait:
trait HasUnderlying { val underlying: Double }
case class Bdrms(val underlying: Double) extends HasUnderlying
And then you can get the desired vector as:
dataCC.productIterator.map {
case h: HasUnderlying => h.underlying
}.toVector

Unpickling when type is unknown

I'm trying to use Scala Pickling to program some generic unpickling logic.
Say you have two types, A and B, and you pickle them into a byte array.
You take this byte array and send it to another machine and that's received as a byte array.
Now you need to unpickle it, but you don't know whether the byte array is for type A or type B.
How would you program the unpicking part? Do you make A and B extend another type, say T, and then call unpickle[T], and then pattern match on the result for A or B?
Or do you add a instance variable to T, say a Byte, which uses different number for instances of type A or B, and based on that, call unpickle[A] or unpickle[B]?
UPDATE: Looking into the Scala Pickling testsuite, the closest thing I found is base.scala, which kinda follows the first option.
The following works by printing:
It's A
It's B
Code:
import scala.pickling._
import binary._
object MultiTypePickling extends App {
sealed abstract class Base
final class A extends Base { override def toString = "A" }
final class B extends Base { override def toString = "B" }
val a = new A
val pa = a.pickle
val b = new B
val pb = b.pickle
// ----
pa.value.unpickle[Base] match {
case aa: A =>
println("It's " + aa)
case _ =>
assert(assertion = false)
}
pb.value.unpickle[Base] match {
case bb: B =>
println("It's " + bb)
case _ =>
assert(assertion = false)
}
}

Why are constructor parameters made into members for case classes?

{
class MyClass(name: String) {}
val x = new MyClass("x")
println(x.name) // Error name is not a member of MyClass
}
but
{
abstract class Base
case class MyClass(name: String) extends Base {}
var x = new MyClass("x")
println(x.name) // name is a member of MyClass
}
So, what's the deal with case classes? Why are all of the constructor parameters turned into variables.
name is member in both examples, but private in your first example while public in your second. Case classes make their constructor parameters public val by default.
Pattern matching is the most important but not the only application for case classes. Another important point is that they implement the equals and hashCode methods in terms of the constructor arguments (aka product elements). Therefore, case classes are very useful for defining data structures that serve as elements in sets or keys in maps. That in turn only makes sense if these elements are visible.
Compare:
class Foo(val i: Int)
val set1 = Set(new Foo(33))
set1.contains(new Foo(33)) // false!!
And:
case class Bar(val i: Int)
val set2 = Set(Bar(33)
set2.contains(Bar(33)) // true!
Two case class instances with equal parameters are equal themselves. You can imagine them representing some "constants". This implies that you should not have mutable state in them.
You can, however, use a second parameter list to exclude arguments from the equality:
case class Baz(i: Int)(val n: Long)
Baz(33)(5L) == Baz(33)(6L) // true!
Another useful feature which implies that the constructor arguments become values, is making copies. This is the way immutable data is changes—you create a new instance with a particular value changed, leaving the original value in place.
case class Person(name: String, age: Int)
val p1 = Person("Fuzzi", 33)
val p2 = p1.copy(age = 34)
The copy method uses default values for all unspecified argument, taking those values from the constructor args.
Just to be clear, the constructor arguments aren't used to create variables, they're used to create values.
If you specify val in your first example, the non-case class:
class MyClass(val name: String) {}
then you also get the argument translated into a public value, the same as is done for the case class.
In the example on the Scala-Lang site it says:
It makes only sense to define case classes if pattern matching is used
to decompose data structures. The following object defines a pretty
printer function for our lambda calculus representation:
followed by the example code:
object TermTest extends Application { def printTerm(term: Term) {
term match {
case Var(n) =>
print(n)
case Fun(x, b) =>
print("^" + x + ".")
printTerm(b)
case App(f, v) =>
Console.print("(")
printTerm(f)
print(" ")
printTerm(v)
print(")")
} } def isIdentityFun(term: Term): Boolean = term match {
case Fun(x, Var(y)) if x == y => true
case _ => false } val id = Fun("x", Var("x")) val t = Fun("x", Fun("y", App(Var("x"), Var("y")))) printTerm(t) println println(isIdentityFun(id)) println(isIdentityFun(t)) }
To add something to my comment due to lack of available space: consider the following example case class:
case class My(x: Int)
If you save it to file and pass it to scalac -print, you get following expanded code (I removed unimportant stuff):
case class My extends Object with Product with Serializable {
<caseaccessor> <paramaccessor> private[this] val x: Int = _;
<stable> <caseaccessor> <accessor> <paramaccessor> def x(): Int = My.this.x;
Notice <caseaccessor>s here.
And then companion object:
<synthetic> object My extends runtime.AbstractFunction1 with Serializable {
case <synthetic> def apply(x: Int): My = new My(x);
case <synthetic> def unapply(x$0: My): Option = if (x$0.==(null))
scala.this.None
else
new Some(scala.Int.box(x$0.x()));
case <synthetic> <bridge> def apply(v1: Object): Object = My.this.apply(scala.Int.unbox(v1));
//...
Notice apply and unapply here. If you look at complete output yourself, you'll learn more about how scala generates your code.