Inherit class with chaining functions - scala

Lets say i have a class with chaining functions
class Vehicle {
protected var position: (Int, Int) = (0, 0)
def moveLeft(meters: Int): Vehicle = {
position = position._1 - meters -> position._2
this
}
def moveForward(meters: Int): Vehicle = {
position = position._1 -> (position._2 + meters)
this
}
}
so each method returns instance itself
Now i want to inherit Vehicle and add some method to new class
class Helicopter extends Vehicle {
protected var verticalDimension: Int = 0
def flyIntoTheSky(meters: Int): Helicopter = {
verticalDimension += meters
this
}
}
If i will create a new class instance and call any functions from parent, for example
new Helicopter().moveLeft(10).moveForward(20)
i will not be able to call new class method flyIntoTheSky because methods return type is Vehicle, and Vehicle does not know anything about methods of Helicopter.
2 obvious ways to solve it:
Either using asInstanceOf
new Helicopter()
.moveLeft(10)
.moveForward(20).asInstanceOf[Helocopter]
.flyIntoTheSky(10000)
either overriding each and avery parental method in new class
Both ways are not looking nice, i would prefer to leave all this type issues to Vehicle class and forget about it, so i found(as i hoped) the solution, rewriting methods like this
def moveLeft[T](meters: Int, vehicle: T = this): T = {
position = position._1 - meters -> position._2
this.asInstanceOf[T]
}
so i expected that return type will be taken from method's second parameter vehicle, which always equals to default value "this", and will return the value of current type. But unfortunately
new Helicopter().moveLeft(10)
still returns value of type Vehicle
res0: Vehicle = Helicopter#1de81c37
So the first question: why it doesn't work as i expected. And the second: is there are any beautiful way to solve this problem
Thank you
PS In google i found this solution in Java
https://www.andygibson.net/blog/article/implementing-chained-methods-in-subclasses/
, but i dont know java and can not translate it in scala

If the method always returns this you can give it return type this.type.
def moveLeft(meters: Int): this.type = {
position = position._1 - meters -> position._2
this
}

Addressing comment
strange, i cant get sense. If this.type refers to Helicopter why def
moveLeft[T](meters: Int, vehicle: T = this): T refers still to Vehicle
Note that this and this.type exist in two separate worlds, although this.type is "encroaching" on the value world as I will attempt to explain bellow. The former is a value whilst latter is a type, although a special kind of type. The type of expression this is not this.type, instead according to SLS:
The expression this... stands for the object being defined by the innermost
template or compound type enclosing the reference. If this is a
compound type, the type of this is that compound type. If it is a
template of a class or object definition with simple name 𝐶, the type
of this is the same as the type of 𝐶.this.
The innermost enclosing class of this in def moveLeft[T](meters: Int, vehicle: T = this): T is in fact Vehicle, therefore the static type of this is Vehicle.
Now consider type this.type:
this . type
| | |
value dot notation type
\ /
-------------------------------
|
value-dependent type
Notice the dot notation . which is used on a value, that is, if this was not a value then we would use # notation like so this#type. However it is indeed a value, which means type type depends on value this. Now, what value does it depend on? Well, no pun intended, it depends. Given the expression new Helicopter() it depends on the value (object) referred to by new Helicopter(), whilst given the expression new Car() it depends on the value referred to by expression new Car(). Important to understand here is that despite the fact that now this.type seems to be "changing" depending on a value, it is still a static type proper, meaning there is no runtime type-checking shenanigans.
I believe the source of confusion stems from the fact that we know, given new Helicopter(), in both cases, this refers to object of class Helicopter at runtime, however the key is to understand what static types can compiler determine, which in turn yields what members are invokable. In the case of this.type the compiler can determine the narrowest possible value-dependent singleton type uniquely inhabited by this very value.
As a side-note here is my attempt using shapeless lenses:
import shapeless._
case class Position(x: Double, y: Double, z: Double = 0)
sealed trait Vehicle
case class Car(p: Position) extends Vehicle
case class Plane(p: Position) extends Vehicle
object Vehicle {
implicit val carPosLens = lens[Car].p
implicit val planePosLens = lens[Plane].p
}
implicit class Move[T <: Vehicle](v: T) {
def moveX(d: Double)(implicit ev: Lens[T, Position]): T = ev.modify(v)(p => p.copy(x = p.x + d))
def moveY(d: Double)(implicit ev: Lens[T, Position]): T = ev.modify(v)(p => p.copy(y = p.y + d))
}
implicit class Fly[T <: Plane](v: T) {
def moveZ(d: Int)(implicit ev: Lens[T, Position]): T = ev.modify(v)(p => p.copy(z = p.z + d))
}
Plane(Position(0,0,0)).moveX(42).moveY(-3.142).moveZ(11)
Car(Position(0,0)).moveX(1)
which outputs
res0: Plane = Plane(Position(42.0,-3.142,11.0))
res1: Car = Car(Position(1.0,0.0,0.0))

Related

Scala cast to generic type

I'm confused about the generic type. I expect that 2.asInstanceOf[A] is cast to the type A, meanwhile, it's cast to Int.
Besides that, the input is java.lang.Long whereas the output is a list of Int (according to the definition the input and the output should be the same type). Why is that?
def whatever[A](x: A): List[A] = {
val two = 2.asInstanceOf[A]
val l = List(1.asInstanceOf[A],2.asInstanceOf[A])
println(f"Input type inside the function for 15L: ${x.getClass}")
println(f"The class of two: ${two.getClass}, the value of two: $two")
println(f"The class of the first element of l: ${l.head.getClass}, first element value: ${l.head}")
l
}
println(f"Returned from whatever function: ${whatever(15L)}")
the outupt:
Input type inside the function for 15L: class java.lang.Long
The class of two: class java.lang.Integer, the value of two: 2
The class of the first element of l: class java.lang.Integer, first element value: 1
Returned from whatever function: List(1, 2)
a.asInstanceOf[B] means:
Dear compiler;
Please forget what you think the type of a is. I know better. I know that if a isn't actually type B then my program could blow up, but I'm really very smart and that's not going to happen.
Sincerely yours, Super Programmer
In other words val b:B = a.asInstanceOf[B] won't create a new variable of type B, it will create a new variable that will be treated as if it were type B. If the actual underlying type of a is compatible with type B then everything is fine. If a's real type is incompatible with B then things blow up.
Type erasure. For the purposes of type checking 2 is cast to A; but at a later compilation stage A is erased to Object, so your code becomes equivalent to
def whatever(x: Object): List[Object] = {
val two = 2.asInstanceOf[Object]
val l = List(1.asInstanceOf[Object],2.asInstanceOf[Object])
println(f"Input type inside the function for 15L: ${x.getClass}")
println(f"The class of two: ${two.getClass}, the value of two: $two")
println(f"The class of the first element of l: ${l.head.getClass}, first element value: ${l.head}")
l
}
2.asInstanceOf[Object] is a boxing operation returning a java.lang.Integer.
If you try to actually use the return value as a List[Long] you'll eventually get a ClassCastException, e.g.
val list = whatever(15L)
val x = list(0)
x will be inferred to be Long and a cast inserted to unbox the expected java.lang.Long.
The answer from #jwvh is on point. Here I'll only add a solution in case you want to fix the problem of safely converting an Int to an A in whatever, without knowing what A is. This is of course only possible if you provide a way to build a particular A from an Int. We can do this in using a type-class:
trait BuildableFromInt[+A] {
def fromInt(i: Int): A
}
Now you only have to implicitly provide BuildableFromInt for any type A you wish to use in whatever:
object BuildableFromInt {
implicit val longFromInt: BuildableFromInt[Long] = Long.box(_)
}
and now define whatever to only accept compliant types A:
def whatever[A : BuildableFromInt](x: A): List[A] = {
val two = implicitly[BuildableFromInt[A]].fromInt(2)
// Use two like any other "A"
// ...
}
Now whatever can be used with any type for which a BuildableFromInt is available.

Missing scodec.Codec[Command] implicit because of class with non-value fields

I'm trying to use discriminators in existing project and something is wrong with my classes I guess.
Consider this scodec example. If I change TurnLeft and its codec to
sealed class TurnLeft(degrees: Int) extends Command {
def getDegrees: Int = degrees
}
implicit val leftCodec: Codec[TurnLeft] = uint8or16.xmap[TurnLeft](v => new TurnLeft(v), _.getDegrees)
I get
Error:(x, x) could not find Lazy implicit value of type scodec.Codec[Command]
val codec: Codec[Either[UnrecognizedCommand, Command]] = discriminatorFallback(unrecognizedCodec, Codec[Command])
It all works if I make degrees field value field. I suspect it's something tricky with shapeless. What should I do to make it work ?
Sample project that demonstrates the issue is here.
shapeless's Generic is defined for "case-class-like" types. To a first approximation, a case-class-like type is one whose values can be deconstructed to it's constructor parameters which can then be used to reconstruct an equal value, ie.
case class Foo ...
val foo = Foo(...)
val fooGen = Generic[Foo]
assert(fooGen.from(fooGen.to(foo)) == foo)
Case classes with a single constructor parameter list meet this criterion, whereas classes which don't have public (lazy) vals for their constructor parameters, or a companion with a matching apply/unapply, do not.
The implementation of Generic is fairly permissive, and will treat (lazy) val members which correspond to constructor parameters (by type and order) as being equivalent to accessible constructor arguments, so the closest to your example that we can get would be something like this,
sealed class TurnLeft(degrees: Int) extends Command {
val getDegrees: Int = degrees
}
scala> Generic[TurnLeft]
res0: shapeless.Generic[TurnLeft]{type Repr = Int :: HNil } = ...
In this case getDegrees is treated as the accessor for the single Int constructor parameter.

Local variables with the same type( generic type parameter) have incompatible type

This issue is related to compiler behavior described in another issue
I think this is related to the way generics are implemented in compiler, and it has something to do with Inner Class compiler feature. I've a similar question and I know that this could be fixed with
if(m.compare(lowerBound.asInstanceOf[m.Measure]) >= 0) {
But I don't want to cast same type to same type all over my code. There should be good explanation why this happens. Should I fill in compiler bug somewhere ?
Without local variable m - error messages get even more weird.
trait MeasureBase {
type Measure <: MeasureBase
def compare(that: Measure): Int
def score: Double
}
case class DocTerm[Measure <: MeasureBase]
(val docID: Long, val measure:Measure)
extends Ordered[DocTerm[Measure]] {
def score = measure.score
def compare(that: DocTerm[Measure]): Int
= measure.compare(that.measure.asInstanceOf[measure.Measure])
}
class WriteCacheIterator[Measure <: MeasureBase]
(data:mutable.ArrayBuffer[DocTerm[Measure]]) {
var position = 0
def Next(lowerBound:Measure):Option[DocTerm[Measure]] = {
if(position < data.size - 1){
val m:Measure = data(position).measure
val b:Measure = lowerBound
if(m.compare(b) >= 0) {
//gives compiler error
//Error:(39, 20) type mismatch;
//found : b.type (with underlying type Measure)
//required: m.Measure
//if(m.compare(b) >= 0) {
}
} else return None
}
}
You have two different definitions for Measure:
the type parameter in DocTerm and other places, which is a subtype of MeasureBase.
a type member inside MeasureBase.
The two have nothing in common (except the name, but they are really different things). There is nothing linking your generic Measure inside WriteCacheIterator to the type member called Measure inside each and every element in your ArrayBuffer. You need to refactor the code to make this constraint explicit.
You could probably refactor the code to only use type parameters (generics) everywhere.
trait MeasureBase[Self <: MeasureBase[Self]] {...}
case class DocTerm[M <: MeasureBase[M](val docID: Long, val measure: M)
...

How to improve type-safety for String- or Double-based values?

I'm wondering the best way to achieve type-safety with my code when various values might all be Strings or Doubles, but are still incompatible. For example, I might have units in pounds and kilograms, but I should be forbidden to assign one to the other. Likewise, I might have a person ID as a String and a lookup table of animal IDs as a Map[String,Int], but I should be forbidden to look a person up in the animals table.
Conceptually I'm looking for something like this:
class PersonId extends String
class AnimalId extends String
var p : PersonId = "1234"
var tab : Map[AnimalId,Int] = Map("foo" -> 5, "bar" -> 6)
tab.get(p) // Want this to cause a compile error
But there are several problems making that not work. Suggestions for something that fits the spirit?
I'd use value classes for this. It behaves pretty much the same as a regular case class but the compiler places some restrictions on it, and generally it never has to actually waste time/memory creating the wrapper object - it can usually use the underlying value directly.
case class Person(value: String) extends AnyVal
case class Animal(value: String) extends AnyVal
You cannot extend String for obvious reasons. I suggest using case classes for that:
case class PersonId(id:String)
case class AnimalId(id:String)
Syntax gets a little bit more complicated, but not that much. And you can use case classes easily when pattern matching!
var p: PersonId = PersonId("1234")
var tab: Map[AnimalId,Int] = Map(AnimalId("foo") -> 5, AnimalId("bar") -> 6)
One simple solution is just use
case class PersonId(id:String)
case class AnimalId(id:String)
This solution is usually good enough.
If you want to play a bit with Scala's type system you can do something like that -
trait Person
trait Animal
case class IdOf[T](s: String) extends AnyVal
implicit def string2idOf[T](s: String): IdOf[T] = IdOf(s)
var p: IdOf[Person] = "1234"
var tab: Map[IdOf[Animal], Int] = Map(("foo": IdOf[Animal]) -> 5, ("bar": IdOf[Animal]) -> 6)
tab.get(p)
// Error:(25, 11) type mismatch;
// found : com.novak.Program.IdOf[com.novak.Program.Person]
// required: com.novak.Program.IdOf[com.novak.Program.Animal]
// tab.get(p)
^
Just another option is Scalaz's tagged type. Might be useful in some cases as it alows you to combine your type with some other type without creating new instance of this other type (value classes do simmilar for primitive types); however new Scalaz requires to explicitly unbox it (with Tag.unwrap), so not much useful as one can expect.
Example:
trait Person
val Person = Tag.of[Person]
val person = Prsn("Me")
Person.unwrap(person)
trait Animal
val Animal = Tag.of[Animal]
val animal = Anml("Me")
Animal.unwrap(person) //error
Animal.unwrap(animal)
Just quotes:
Suppose we want a way to express mass using kilogram, because kg is
the international standard of unit. Normally we would pass in Double
and call it a day, but we can’t distinguish that from other Double
values. Can we use case class for this?
case class KiloGram(value: Double)
Although it does adds type safety,
it’s not fun to use because we have to call x.value every time we need
to extract the value out of it. Tagged type to the rescue.
scala> sealed trait KiloGram defined trait KiloGram
scala> def KiloGram[A](a: A): A ## KiloGram = Tag[A, KiloGram](a)
KiloGram: [A](a: A)scalaz.##[A,KiloGram]
scala> val mass = KiloGram(20.0) mass: scalaz.##[Double,KiloGram] =
20.0
scala> sealed trait JoulePerKiloGram
defined trait JoulePerKiloGram
scala> def JoulePerKiloGram[A](a: A): A ## JoulePerKiloGram = Tag[A, JoulePerKiloGram](a)
JoulePerKiloGram: [A](a: A)scalaz.##[A,JoulePerKiloGram]
scala> def energyR(m: Double ## KiloGram): Double ## JoulePerKiloGram =
JoulePerKiloGram(299792458.0 * 299792458.0 * Tag.unsubst[Double, Id, KiloGram](m))
energyR: (m: scalaz.##[Double,KiloGram])scalaz.##[Double,JoulePerKiloGram]
scala> energyR(mass)
res4: scalaz.##[Double,JoulePerKiloGram] = 1.79751035747363533E18
scala> energyR(10.0)
<console>:18: error: type mismatch;
found : Double(10.0)
required: scalaz.##[Double,KiloGram]
(which expands to) AnyRef{type Tag = KiloGram; type Self = Double}
energyR(10.0)
^

Using scala generics and manifest to cast within a class

I have two classes, Holders (for lack of a better name at the moment) and Holder.
Holder has to be interfaced through Holders, which has an array of Holder of any type.
As such, it has to take Any type. I want to have the setValue do type checking that the Any input is indeed of type T.
I've read a bit about using manifests, but I'm getting somewhat lost. Is there any way to do what I want?
class Holders {
var values = Array[Any]()
var _holders = Array[Holder[_]]()
def setData(index: Int, newValue: Any) {
values(index) = newValue
_holders(index).setValue(newValue)
}
}
class Holder[T](someData: String, initValue: T) {
private var value : T = initValue
def getValue : T = value
def setValue(newValue: Any)(implicit m: Manifest[T]) = {
if (newValue.isInstanceOf[T])
value = newValue.asInstanceOf[T]
}
}
You can.
note: Manifest is deprecated and replaced with TypeTag and ClassTag, but that doesn't affect the remainder of this answer
Often when wanting Manifests/TypeTags you know exactly what's happening at compile time but want that information preserved through to runtime as well. In this case you also have to deal with the fact that, even at compile time, _holders(index) can't tell you what kind of Holder it's returning.
Depending on how _holders will be built, it may be possible to replace it with an Heterogeneous Map from the shapeless library, that would do exactly what you need out-of-the-box.
Otherwise, you have the right idea, testing the type at runtime. The trick is using TypeTag to capture both the underlying type of the holder and the type of the new value.
Note that the TypeTag context bound has to be specified on all the nested methods so it can be passed down the call stack in implicit scope. Presence of the TypeTag is what allows typeOf to then work.
import scala.reflect.runtime.universe._ //for TypeTag
class Holders {
var values = Array[Any]()
var _holders = Array[Holder[_]]()
def setData[V: TypeTag](index: Int, newValue: V): Unit = {
values(index) = newValue
_holders(index).setValue(newValue)
}
}
class Holder[T: TypeTag](someData: String, initValue: T) {
private var value: T = initValue
def getValue: T = value
def setValue[V: TypeTag](newValue: V): Unit =
if(typeOf[V] <:< typeOf[T]) {
value = newValue.asInstanceOf[T]
}
Or using Manifest
class Holder[T: Manifest](someData: String, initValue: T) {
private var value: T = initValue
def getValue: T = value
def setValue[V: Manifest](newValue: V): Unit =
if(manifest[V] <:< manifest[T]) {
value = newValue.asInstanceOf[T]
}
I'd strongly urge you to favour TypeTag though!
Type erasure makes this kind of thing... hard. In a nutshell once your code is compiled, all type parameters are replaced with Any. To understand the implications, consider the following example:
trait Foo[T] { def isT(a: Any): Boolean = a.isInstanceOf[T] }
object Bar extends Foo[String]
Bar.isT("foo") // true
Bar.isT(42) // also true, as Int <: Any
This will produce a warning when compiled with the appropriate options.
In this scenario you have two options; you can compare TypeTags, in which case you hope that the provided type parameters are sufficiently accurate (consider the provided type parameter could be any superclass of value), or you compare the runtime classes of your values (in which case you are out of luck when dealing with generic types). A TypeTag-based solution might look something like this:
class Holder[T : TypeTag](someData: String, initValue: T) {
private var value = initValue
def setValue[V : TypeTag](v: V): Unit = {
// Works because there are TypeTags for T and V in implicit scope
if(typeOf[V] <:< typeOf[T])
value = v.asInstanceOf[T]
}
}
Now you are looking at this and saying "well doesn't that mean that the assignment is actually value = v.asInstanceOf[Any]?" and the answer is yes - value is also erased to Any. Casting does nothing, in the sense that v.asInstanceOf[T] does not mean "convert v to a T". Instead what you are doing is saying "oh yeah, v is totally a T - honest!", and because the compiler is naive, it believes you.