type inference & generics in scala - scala

I'm doing the following function to return a new figure from another, but Scala is inferring the result as Figure and I want it to be the figure in particular, as a circle, etc.
How could I do to infer the particular figure? I have been told to use generics to solve it, how would this be?
trait Figure {
def x:Int
def y:Int
}
case class Circle(x:Int, y: Int, radio: Double)
extends Figure
case class Rectangle(x:Int, y: Int, width: Int, high: Int)
extends Figure
object Motor {
def move[T](x: Int, y: Int, figure: T) :Figure = figure match {
case Circle(xPos, yPos, radio) => Circle(xPos+x, yPos+y, radio)
case Rectangle(xPos, yPos, width, high) => Rectangle(xPos+x, yPos+y, width, high)
}
}

Here's is a more concise, perhaps a bit less intimidating version of Sarvesh Kumar Singh's suggestion to use a typeclass. I think that is the best approach all around. It gives you typesafe functionality while letting you keep your basic types very simple.
trait Figure {
def x:Int
def y:Int
}
case class Circle(x:Int, y: Int, radius: Double) extends Figure
case class Rectangle(x:Int, y: Int, width: Int, height: Int) extends Figure
trait Movable[T] {
def move( x: Int, y: Int, movable: T ) : T
}
implicit final object CircleIsMovable extends Movable[Circle] {
def move( x: Int, y: Int, c: Circle ) = Circle( c.x + x, c.y + y, c.radius )
}
implicit final object RectangleIsMovable extends Movable[Rectangle] {
def move( x: Int, y: Int, r: Rectangle ) = Rectangle( r.x + x, r.y + y, r.width, r.height )
}
object Motor {
def move[T : Movable](x: Int, y: Int, movable: T) : T = implicitly[Movable[T]].move( x, y, movable )
}
Then...
scala> Motor.move(10,10,Circle(0,0,1))
res1: Circle = Circle(10,10,1.0)
scala> Motor.move(10,10,Rectangle(0,0,1,1))
res2: Rectangle = Rectangle(10,10,1,1)

You should make it so that the "move" happens on the type T itself and return type T. But then the compiler will complain about not being sure that you are returning a T because the actual type of T will be determined for the use of move and compiler has no evidence to determine that it was a Circle as match-case is a runtime thing.
Which means you need to provide evidence which can be used at compile-time to move any instance of type T.
import scala.language.implicitConversions
trait Figure {
def x:Int
def y:Int
}
case class Circle(x:Int, y: Int, radio: Double)
extends Figure
case class Rectangle(x:Int, y: Int, width: Int, high: Int)
extends Figure
Now, let us build the required evidence which will be used to "enrich" our Figure instances
trait MoveSupport[F <: Figure] {
val f: F
def move(x: Int, y: Int): F
}
object MoveSupport {
class CircleMoveSupport(val f: Circle) extends MoveSupport[Circle] {
override def move(x: Int, y: Int): Circle = f.copy(x = f.x + x, y = f.y + y)
}
class RectangleMoveSupport(val f: Rectangle) extends MoveSupport[Rectangle] {
override def move(x: Int, y: Int): Rectangle = f.copy(x = f.x + x, y = f.y + y)
}
implicit def toCircleMoveSupport(circle: Circle) = new CircleMoveSupport(circle)
implicit def toRectangleMoveSupport(rectangle: Rectangle) = new RectangleMoveSupport(rectangle)
}
Now, we can use these evidence to "enrich" our Figure types to have move support.
import MoveSupport._
val circle = Circle(1, 1, 1)
// circle: Circle = Circle(1,1,1.0)
val circle2 = circle.move(1, 1)
// circle2: Circle = Circle(2,2,1.0)
Or, you can build your Motor using these evidence.
object Motor {
import MoveSupport._
def move[T <: Figure](x: Int, y: Int, figure: T)(implicit ev: T => MoveSupport[T]): T = figure.move(x, y)
}
val c = Circle(1, 1, 1)
// circle: Circle = Circle(1,1,1.0)
val c1 = Motor.move(1, 1, c)
// circle1: Circle = Circle(2,2,1.0)

Maybe what you are after is something like
object Motor {
def move[T <: Figure](x: Int, y: Int, figure: T): T = {
val moved = figure match {
case Circle(xPos, yPos, radio) => Circle(xPos+x, yPos+y, radio)
case Rectangle(xPos, yPos, width, high) => Rectangle(xPos+x, yPos+y, width, high)
}
moved.asInstanceOf[T]
}
}

You may want to consider moving the implementation of move to the various classes. Here is an example that uses abstract types to enable the method to return the type of the object:
trait Figure {
def x: Int
def y: Int
type Self <: Figure
def move(dx: Int, dy: Int): Self
}
case class Circle(x: Int, y: Int, radius: Double) extends Figure {
type Self = Circle
def move(dx: Int, dy: Int): Circle = copy(x = x + dx, y = y + dy)
}
case class Rectangle(x: Int, y: Int, widht: Int, height: Int) extends Figure {
type Self = Rectangle
def move(dx: Int, dy: Int): Rectangle = copy(x = x + dx, y = y + dy)
}

Related

When to use override in Scala class?

Here's an example that confused me a lot.
class Point(val xc: Int, val yc: Int) {
var x: Int = xc
var y: Int = yc
def move(dx: Int, dy: Int) {
x = x + dx
y = y + dy
println ("x 的坐标点 : " + x);
println ("y 的坐标点 : " + y);
}
}
class Location(override val xc: Int,
override val yc: Int,
val zc: Int) extends Point(xc, yc) {
var z: Int = zc
def move(dx: Int, dy: Int, dz: Int) {
x = x + dx
y = y + dy
z = z + dz
println ("x 的坐标点 : " + x);
println ("y 的坐标点 : " + y);
println ("z 的坐标点 : " + z);
}
}
Why does the method move not need an override modifier? It isn't an abstract method in class Point, it should be decorated with "override", I think. Actually, when I add an "override", error happens.
And for xc, yc, why "override" is a nessesary?
I'm really confused with that.
I have python experience and very little Java experience.
Any help will be appreciated, thanks!
for xc, yc, why "override" is a nessesary?
Nope, its not necessary. In your case you're making it val again in your child class, which is not necessary since you already defined them as val in parent class. (simply remove val from child class)
scala> class Point(val xc: Int, val yc: Int) {}
defined class Point
scala> class Location(xc: Int, yc: Int, val zc :Int) extends Point(xc, yc){}
defined class Location
Why the method "move" doesn't need an "override"?
Because your move method in Parent class is not an abstract method
or your signature is different in child class than parent class.
eg.
abstract class Point(val xc: Int, val yc: Int) {
abstract def doWhatever() : Unit
}
class Location(xc: Int, yc: Int, val zc: Int) extends Point(xc, yc) {
override def doWhatever(): Unit = ??? // override is optional
}
You could have aldo overridden if the signature was same, so that when you call childClass.move(), the overridden method is invoked.
class Point(val xc: Int, val yc: Int) {
def move() = println("parent::whatever")
}
class Location(xc: Int, yc: Int, val zc: Int) extends Point(xc, yc) {
override def move() = println("child::whatever") //override is required
}
example invoking move method,
for a parent,
scala> val point = new Point(1, 2)
point: Point = Point#66813e6e
scala> point.move()
parent::whatever
for a child,
scala> val location1 = new Location(1, 2, 3)
location1: Location = Location1#233db8e9
scala> location1.move()
child::whatever

How to compute a value to pass into a primary constructor from an auxiliary constructor?

I want to define an auxiliary constructor which should compute some value and use it in multiple parameters passed to a primary constructor. A natural way to express this would be to define local vals before calling the primary constructor, but this is not allowed by the language:
object Computed {
def veryComplexComputation(x: Double) = math.sqrt(x) // imagine there is some much more complex computation here
}
class Computed(x: Double, y: Double, z: Double) {
def this(x: Double, y: Double) = {
val derivedFromX = Computed.veryComplexComputation(x)
val derivedFromY = derivedFromX * Computed.veryComplexComputation(y)
this(x, derivedFromX, derivedFromY)
}
}
An alternative is to repeat the computation, but with very complex computations this can be a problem (and it also leads to a code repetition):
class Computed(x: Double, y: Double, z: Double) {
def this(x: Double, y: Double) = {
this(
x,
Computed.veryComplexComputation(x),
Computed.veryComplexComputation(x) * Computed.veryComplexComputation(y)
)
}
}
The best trick I know is to use a third, private constructor taking a tuple of the parameters for the primary constructor, together with a helper function in the companion object:
object Computed {
def veryComplexComputation(x: Double) = math.sqrt(x) // imagine there is some much more complex computation here
private def computeArgs(x: Double, y: Double): (Double, Double, Double) = {
val derivedFromX = veryComplexComputation(x)
val derivedFromY = derivedFromX * veryComplexComputation(y)
(x, derivedFromX, derivedFromY)
}
}
class Computed(x: Double, y: Double, z: Double) {
private def this(xyz: (Double, Double, Double)) =
this(xyz._1, xyz._2, xyz._3)
def this(x: Double, y: Double) =
this(Computed.computeArgs(x, y))
}
I think the best way is to add a suitable factory method to the companion object:
object Computed {
def veryComplexComputation(x: Double) = math.sqrt(x) // can be private, if you wish
def apply(x: Double, y: Double): Computed = {
val derivedFromX = veryComplexComputation(x)
val derivedFromY = derivedFromX * veryComplexComputation(y)
new Computed(x, derivedFromX, derivedFromY)
}
}
then you can instantiate your Computed type the same way as for case classes, foregoing the use of "new":
scala> val comp = Computed(4.0, 9.0)
comp: Computed = Computed#4de4e24f
(You might also want to consider making Computed a case class anyway - particularly if is entirely, or even mostly, used as a container for data)
One can (ab)use multiple parameter lists with default values, like this:
class Computed(x: Double, y: Double, z: Double) {
def this(x: Double, y: Double)(
derivedFromX: Double = Computed.veryComplexComputation(x)
)(
derivedFromY: Double = derivedFromX * Computed.veryComplexComputation(y)
) = {
this(x, derivedFromX, derivedFromY)
}
}
This exploits the fact each parameter list can access parameters from previous lists. Just do not forget to provide the empty parameter lists when calling the constructor:
new Computed(1, 2)()()
One can chain several auxiliary constructors, each of them performing one computation, using marker traits to distinguish between constructors to avoid overloading ambiguity.
object Computed {
def veryComplexComputation(x: Double) = math.sqrt(x) // imagine there is some much more complex computation here
private trait DerivedFromX
private object DerivedFromX extends DerivedFromX
}
class Computed(x: Double, y: Double, z: Double) {
private def this(name: Computed.DerivedFromX, x: Double, derivedFromX: Double, y: Double) = {
this(x, derivedFromX, derivedFromX * Computed.veryComplexComputation(y))
}
def this(x: Double, y: Double) = this(Computed.DerivedFromX, x, Computed.veryComplexComputation(x), y)
}

How do I write a scala extractor for a case class with default parameters?

I have the following case class with a default parameter and I'm wondering how I can write an unapply method so that I can just extract the first two parameters.
I hope the code below is clear.
case class Point(x: Double, y: Double, _key: Option[String] = None) {
def key: String = _key.getOrElse("")
}
object Point {
def unapply(p: Point) = (p.x, p.y)
}
// pSeq is Seq[Point]
pSeq.map { case Point(x,y) => x + y } // This causes a compiler error:
// wrong number of arguments for <none>:
// (x: Double, y: Double, _key: Option[String])
I'm not sure if this is what you are looking for, but it would give you the API that you describe.
sealed abstract class Point(x: Double, y: Double)
case class PointKey(x: Double, y: Double, _key: String) extends Point(x,y)
case class PointNoKey(x: Double, y: Double) extends Point(x,y)
object Point {
def apply(x: Double, y: Double) = PointNoKey(x,y)
def apply(x: Double, y: Double, _key: String) = PointKey(x,y,_key)
def unapply(p: Point): Option[(Double,Double)] = p match {
case PointNoKey(x,y) => Some(x,y)
case PointKey(x,y,_) => Some(x,y)
}
}
I think that just using a wildcard in the case class is preferred if that will work for you.
pSeq.map { case Point(x,y,_) => x + y }

Rectangle Class (objects) can have two intrinsic parameters length and width. How to write (independent) function to calculate the area?

Here is the code I have written for Rectangle class.
class Rectangle (l: Double, w: Double) {
require (l > 0, w > 0)
val length = l
val width = w
def this (l: Double) = this (l, l)
def setDimensions (l: Double, w: Double) = new Rectangle (l, w)
def setLength (l: Double) = new Rectangle (l, width)
def setWidth (w: Double) = new Rectangle (length, w)
}
My question is how to write following functions (independent of Rectangle class) in Scala:
Given the length and width calculate the area of the Rectangle
Given the length and area calculate the width of the Rectangle
Given the width and area calculate the length of the Rectangle
Given the Rectangle Object show the length, width and area
This question arose after going through the following paragraph from this article:
Functional languages get their name from the concept that programs should behave like mathematical functions; in other words, given a set of inputs, a function should always return the same output. Not only does this mean that every function must return a value, but that functions must inherently carry no intrinsic state from one call to the next. This intrinsic notion of statelessness, carried over into the functional/object world to mean immutable objects by default, is a large part of why functional languages are being hailed as the great saviors of a madly concurrent world.
Please note that as Scala beginner, I am trying to grasp the FP part of it.
Here is an example for you:
case class Rectangle(length: Double, width: Double) {
require (length > 0, width > 0)
lazy val area = length * width
override def toString = s"length: $length, width: $width, area: $area"
}
object Rectangle {
def fromLength(length: Double) = Rectangle(length, length)
def fromLengthArea(length: Double, area: Double) = Rectangle(length, area / length)
def fromWidthArea(width: Double, area: Double) = Rectangle(area / width, width)
def show(rect: Rectangle) = println(rect)
}
// Usage
Rectangle show Rectangle(2, 3)
Rectangle show Rectangle.fromLength(2)
Rectangle show Rectangle.fromLengthArea(2, 6)
Rectangle show Rectangle.fromWidthArea(3, 6)
I can recommend you to always case classes where it's appropriate, especially for classes like Rectangle.
show method needs to print results, so you can't avoid side-effects in this case. In other words this function is not referentialy transparent. Actually, the whole constructor of Rectangle can be considered not referentialy transparent because you are using require. You can avoid this by insuring, that Rectangle will always receive correct values somewhere outside the class, but you also need to return something, when Rectangle class cannot be created because of validation errors. You can use Option class for this purpose. Here is little example of this:
case class Rectangle private (length: Double, width: Double) {
lazy val area = length * width
override def toString = s"length: $length, width: $width, area: $area"
}
object Rectangle {
def fromLengthWidth(length: Double, width: Double) =
validating(length, width)(new Rectangle(length, width))
def fromLength(length: Double) = validating(length) {
new Rectangle(length, length)
}
def fromLengthArea(length: Double, area: Double) = validating(length, area) {
new Rectangle(length, area / length)
}
def fromWidthArea(width: Double, area: Double) = validating(width, area) {
new Rectangle(area / width, width)
}
def show(rect: Option[Rectangle]) = println(rect getOrElse "Invalid Rectangle!!!")
private def validating[R](values: Double*)(fn: => R) =
if (values forall (_ > 0)) Some(fn)
else None
}
Rectangle show Rectangle.fromLengthWidth(2, 3)
Rectangle show Rectangle.fromLength(0)
// prints:
// length: 2.0, width: 3.0, area: 6.0
// Invalid Rectangle!!!
As you can see I made constructor private and moved validation in the companion object (which can access private member of the class with the same name). So you can't create invalid rectangle. But important point here, is that even if you provide broken length, you still receive something (in this case it's None object which is instance and subclass of Option class).
I added area method to the class, but you can of course write an independent method or function that calculates area:
def area(rect: Rectangle) = rect.length * rect.width
or
val area = (rect: Rectangle) => rect.length * rect.width
I hope this will help you in understanding this topic. If it's still not clear (or my answer does not cover what you actually wanted to know), please don't hesitate and leave a comment.
Here is implementation of the functions you described:
def area(length: Double, width: Double) = length * width
def length(width: Double, area: Double) = if (width > 0) area / width else 0
def width(length: Double, area: Double) = if (length > 0) area / length else 0
def show(rect: Rectangle) =
println(rect.length + ", " + rect.width + ", " + area(rect.length, rect.width))
I was curious how to do this with type classes and so I came up with this version, that will not even allow you to compile code with invalid Rectangles. I bet this can be done a little cleaner, but this is what I quickly put together:
trait LengthCalc[-A] {
def length(x: A): Double
}
trait WidthCalc[-A] {
def width(x: A): Double
}
trait AreaCalc[-A] {
def area(x: A): Double
}
case class Rectangle[A <: Option[Double], B <: Option[Double], C <: Option[Double]](lengthOpt: A = None, widthOpt: B = None, areaOpt: C = None)
(implicit lengthCalc: LengthCalc[Rectangle[A,B,C]], widthCalc: WidthCalc[Rectangle[A,B,C]], areaCalc: AreaCalc[Rectangle[A,B,C]]) {
lazy val length = lengthCalc.length(this)
lazy val width = widthCalc.width(this)
lazy val area = areaCalc.area(this)
}
implicit object RectLengthCalcFromLength extends LengthCalc[Rectangle[Some[Double], _ <: Option[Double], _ <: Option[Double]]] {
def length(x: Rectangle[Some[Double], _ <: Option[Double], _ <: Option[Double]]) = x.lengthOpt.get
}
implicit object RectLengthCalcFromWidthAndArea extends LengthCalc[Rectangle[None.type, Some[Double], Some[Double]]] {
def length(x: Rectangle[None.type, Some[Double], Some[Double]]) = (for {
area <- x.areaOpt
width <- x.widthOpt
} yield (area / width)).get
}
implicit object RectWidthFromWidth extends WidthCalc[Rectangle[_ <: Option[Double], Some[Double], _ <: Option[Double]]] {
def width(x: Rectangle[_ <: Option[Double], Some[Double], _ <: Option[Double]]) = x.widthOpt.get
}
implicit object RectWidthFromLengthAndArea extends WidthCalc[Rectangle[Some[Double], None.type, Some[Double]]] {
def width(x: Rectangle[Some[Double], None.type, Some[Double]]) = (for {
area <- x.areaOpt
length <- x.lengthOpt
} yield (area / length)).get
}
implicit object RectAreaFromArea extends AreaCalc[Rectangle[_ <: Option[Double], _ <: Option[Double], Some[Double]]] {
def area(x: Rectangle[_ <: Option[Double], _ <: Option[Double], Some[Double]]) = {
x.areaOpt.get
}
}
implicit object RectAreaFromLengthAndWidth extends AreaCalc[Rectangle[Some[Double], Some[Double], None.type]] {
def area(x: Rectangle[Some[Double], Some[Double], None.type]) = (for {
width <- x.widthOpt
length <- x.lengthOpt
} yield (width * length)).get
}
Here are some example calls:
scala> Rectangle(Some(3.),None,Some(4.))
res8: Rectangle[Some[Double],None.type,Some[Double]] = Rectangle(Some(3.0),None,Some(4.0))
scala> res8.width
res9: Double = 1.3333333333333333
scala> Rectangle(Some(3.),None,None)
<console>:25: error: could not find implicit value for parameter widthCalc: WidthCalc[Rectangle[Some[Double],None.type,None.type]]
Rectangle(Some(3.),None,None)
scala> Rectangle(None, Some(8.), Some(64.))
res10: Rectangle[None.type,Some[Double],Some[Double]] = Rectangle(None,Some(8.0),Some(64.0))
scala> res10.length
res11: Double = 8.0

Swappable Trait in Scala

I want to define a Swappable trait with two values x,y and a swap method such that calling swap on an object inheriting from Swappable returns another object of the same type with x,y switched. My best so far is:
trait Swappable[T] {
val x: T
val y: T
def swap: Swappable[T] = {
val (a,b) = (x,y)
new Swappable[T] { val x=b; val y=a }
}
}
But this isn't what I want because the return type of swap is some anonymous class, instead of the original class I started with, so I get errors like:
def direct[S<:Swappable[Int]](s: S): S = if (s.x > s.y) s else s.swap
<console>:32: error: type mismatch;
found : Swappable[Int]
required: S
def direct[S<:Swappable[Int]](s: S): S = if (s.x > s.y) s else s.swap
^
Is it possible to do what I'm trying to do? What is the correct type signature for swap?
I don't know how to do it, but I think maybe it would help to get a better idea of what exactly you want to happen. Consider a class like
case class Foo(x: Int, y: Int) extends Swappable[Int] {
val z = x
}
Now, if you have f = Foo(1, 2), should f.swap give you a Foo where x != z? If so, there's no way within Scala to create a Foo like that. If not, what does it really mean to "swap x and y"?
Perhaps what you're really looking for is something like this:
trait Swappable[A,T] {
this: A =>
val x: T
val y: T
def cons(x: T, y: T): A
def swap = cons(y, x)
}
case class Foo(x: Int, y: Int) extends Swappable[Foo,Int] {
val z = x
def cons(x: Int, y: Int) = copy(x=x, y=y)
}
But I'm not sure.
What about something like that:
trait Swappable[T] {
type A
val x: T
val y: T
def create(a: T, b: T): A
def swap = create(y, x)
}
case MySwappable[T](x: T, y: T) extends Swappable[T] {
type A = MySwappable
def create(a: T, b: T) = MySwappable(a, b)
}