How to override predefined function in Scala? - scala

I need to implement function to. I have the following working code:
object Main {
val m = 0
val km = 1
implicit def wrapM(v: Int) = new {
def m = v
}
implicit def wrapKm(v: Int) = new {
def km = v * 1000
}
implicit class toWrap(fromVal: Int) {
def too (value: Int): Double = {
if (value.equals(km)) {
fromVal / 1000.0
} else {
0
}
}
}
def main(args:Array[String])
{
println(53.m too km)
}
}
But there is one problem. I use too name, instead of to. If I rename it to to, then I get the error:
Error:(30, 16) type mismatch;
found : Int
required: ?{def to(x$1: ? >: Int): ?}
Note that implicit conversions are not applicable because they are ambiguous:
both method intWrapper in class LowPriorityImplicits of type (x: Int)scala.runtime.RichInt
and method toWrap in object Main of type (fromVal: Int)Main.toWrap
are possible conversion functions from Int to ?{def to(x$1: ? >: Int): ?}
println(53.m to km)
^
It is due to the fact, that there is one other function to - scala.runtime.RichInt#to.

Scala does not allow define two implicits with same arguments set in one context....
But there is a way. You should work with different type in toWrap implicit , instead of standard scala Int.
Check sample below.
My idea is to implement method to for some wrapper class IntWrap instead of standard Int
case class IntWrap(v: Int) {
}
val m = 0
val km = 1
implicit def wrapM(v: Int) = new {
def m = IntWrap(v)
}
implicit def wrapKm(v: Int) = new {
def km = v * 1000
}
implicit class toWrap(fromVal: IntWrap) {
def to(value: Int): Double = {
if (value.equals(km)) {
fromVal.v / 1000.0
} else {
0
}
}
}
def main(args:Array[String])
{
println(53.m to km)
}

Related

Scala Method on Generic Data Type

I am trying to create a generic class that only accepts java.math.BigDecimal or Long. Here is the code:
class myClass[T]()
{
def display( x : T) = {
println(x.doubleValue())
}
}
val input = new java.math.BigDecimal(100)
// val input = 100L
val x = new myClass[java.math.BigDecimal]()
x.display(input)
Clearly I will have this error: ScalaFiddle.scala:22: error: value doubleValue is not a member of type parameter T.
I tried playing with implicit conversion, view bound, and context bound for hours. No result so far. Is there any way I can force Scala to believe me that T has method .doubleValue()? (java.big.Decimal and Long both has .doubleValue() method, but they don't share same super-class)
Try structural type bound
class myClass[T <: {def doubleValue(): Double}]
or type class
trait HasDoubleValue[T] {
def doubleValue(t: T): Double
}
object HasDoubleValue {
implicit val long: HasDoubleValue[Long] = t => t.doubleValue
implicit val bigDecimal: HasDoubleValue[BigDecimal] = t => t.doubleValue
}
implicit class DoubleValueOps[T: HasDoubleValue](x: T) {
def doubleValue(): Double = implicitly[HasDoubleValue[T]].doubleValue(x)
}
class myClass[T: HasDoubleValue]
In Dotty (Scala 3) we might use union types, for example,
class myClass[T <: (Long | java.math.BigDecimal)]() {
def display(x: T) =
println(
x match {
case t: Long => t.doubleValue
case t: java.math.BigDecimal => t.doubleValue
}
)
}
new myClass().display(new java.math.BigDecimal(100)) // OK
new myClass().display(100L) // OK
new myClass().display("100") // Error
scala> class C private (n: Number) {
| def this(i: Long) = this(i: Number)
| def this(b: BigDecimal) = this(b: Number)
| def d = n.doubleValue
| }
defined class C
scala> new C(42L).d
res0: Double = 42.0
scala> new C(BigDecimal("123456789")).d
res1: Double = 1.23456789E8
or with a type parameter
scala> class C[A <: Number] private (n: A) { def d = n.doubleValue ; def a = n } ; object C {
| def apply(i: Long) = new C(i: Number) ; def apply(b: BigDecimal) = new C(b) }
defined class C
defined object C

why scala compiler says type arguments does not conform to bounds?

I created Combiner trait with subclasses Complex and IntCombiner and my objective is to make Matrix work with both Complex and Int. But some reason it dosen't compile saying that
[com.implicits.TestImplicits1.IntCombiner] do not conform to class Matrix's type parameter bounds [T <: com.implicits.TestImplicits1.Combiner[T]]
val m1 = new Matrix[IntCombiner](3, 3)((1 to 9).sliding(3).map {
But as my understanding goes as IntContainer is the subclass of Combiner it should work. Why such an error please explain ?
object TestImplicits1 {
trait Combiner[T] {
def +(b: T): T
def *(b: T): T
}
class Complex(r: Double, i: Double) extends Combiner[Complex] {
val real = r
val im = i
override def +(b: Complex): Complex = {
new Complex(real + b.real, im + b.im)
}
override def *(b: Complex): Complex = {
new Complex((real * b.real) - (im * b.im), real * b.im + b.real * im)
}
}
class IntCombiner(a: Int) extends Combiner[Int] {
val v = a
override def *(b: Int): Int = v * b
override def +(b: Int): Int = v + b
}
class Matrix[T <: Combiner[T]](x1: Int, y1: Int)(ma: Seq[Seq[T]]) {
self =>
val x: Int = x1
val y: Int = y1
def dot(v1: Seq[T], v2: Seq[T]): T = {
v1.zip(v2).map { t: (T, T) => {
t._1 * t._2
}
}.reduce(_ + _)
}
}
object MatrixInt extends App {
def apply[T <: Combiner[T]](x1: Int, y1: Int)(s: Seq[Seq[T]]) = {
new Matrix[T](x1, y1)(s)
}
val m1 = new Matrix[IntCombiner](3, 3)((1 to 9).sliding(3).map {
x => x map { y => new IntCombiner(y) }
}.toSeq)
}
}
F-bounded polymorphism cannot be added to an existing Int class, because Int is just what it is, it does not know anything about your Combiner traits, so it cannot extend Combiner[Int]. You could wrap every Int into something like an IntWrapper <: Combiner[IntWrapper], but this would waste quite a bit of memory, and library design around F-bounded polymorphism tends to be tricky.
Here is a proposal based on ad-hoc polymorphism and typeclasses instead:
object TestImplicits1 {
trait Combiner[T] {
def +(a: T, b: T): T
def *(a: T, b: T): T
}
object syntax {
object combiner {
implicit class CombinerOps[A](a: A) {
def +(b: A)(implicit comb: Combiner[A]) = comb.+(a, b)
def *(b: A)(implicit comb: Combiner[A]) = comb.*(a, b)
}
}
}
case class Complex(re: Double, im: Double)
implicit val complexCombiner: Combiner[Complex] = new Combiner[Complex] {
override def +(a: Complex, b: Complex): Complex = {
Complex(a.re + b.re, a.im + b.im)
}
override def *(a: Complex, b: Complex): Complex = {
Complex((a.re * b.re) - (a.im * b.im), a.re * b.im + b.re * a.im)
}
}
implicit val intCombiner: Combiner[Int] = new Combiner[Int] {
override def *(a: Int, b: Int): Int = a * b
override def +(a: Int, b: Int): Int = a + b
}
class Matrix[T: Combiner](entries: Vector[Vector[T]]) {
def frobeniusNormSq: T = {
import syntax.combiner._
entries.map(_.map(x => x * x).reduce(_ + _)).reduce(_ + _)
}
}
}
I don't know what you attempted with dot there, your x1, x2 and ma seemed to be completely unused, so I added a simple square-of-Frobenius-norm example instead, just to show how the typeclasses and the syntactic sugar for operators work together. Please don't expect anything remotely resembling "high performance" from it - JVM traditionally never cared about rectangular arrays and number crunching (at least not on a single compute node; Spark & Co is a different story). At least your code won't be automatically transpiled to optimized CUDA code, that's for sure.

In Scala, how to deal with heterogeneous list of the same parameterized type

I have an array of Any (in real life, it's a Spark Row, but it's sufficient to isolate the problem)
object Row {
val buffer : Array[Any] = Array(42, 21, true)
}
And I want to apply some operations on its elements.
So, I've defined a simple ADT to define a compute operation on a type A
trait Op[A] {
def cast(a: Any) : A = a.asInstanceOf[A]
def compute(a: A) : A
}
case object Count extends Op[Int] {
override def compute(a: Int): Int = a + 1
}
case object Exist extends Op[Boolean] {
override def compute(a: Boolean): Boolean = a
}
Given that I have a list of all operations and I know which operation is to apply to each element, let's use these operations.
object GenericsOp {
import Row._
val ops = Seq(Count, Exist)
def compute() = {
buffer(0) = ops(0).compute(ops(0).cast(buffer(0)))
buffer(1) = ops(0).compute(ops(0).cast(buffer(1)))
buffer(2) = ops(1).compute(ops(1).cast(buffer(2)))
}
}
By design, for a given op, types are aligned between cast and combine. But unfortunately the following code does not compile. The error is
Type mismatch, expected: _$1, actual: AnyVal
Is there a way to make it work ?
I've found a workaround by using abstract type member instead of type parameter.
object AbstractOp extends App {
import Row._
trait Op {
type A
def compute(a: A) : A
}
case object Count extends Op {
type A = Int
override def compute(a: Int): Int = a + 1
}
case object Exist extends Op {
type A = Boolean
override def compute(a: Boolean): Boolean = a
}
val ops = Seq(Count, Exist)
def compute() = {
val op0 = ops(0)
val op1 = ops(1)
buffer(0) = ops(0).compute(buffer(0).asInstanceOf[op0.A])
buffer(1) = ops(0).compute(buffer(1).asInstanceOf[op0.A])
buffer(2) = ops(1).compute(buffer(2).asInstanceOf[op1.A])
}
}
Is there a better way ?
It seems that your code can be simplified by making Op[A] extend Any => A:
trait Op[A] extends (Any => A) {
def cast(a: Any) : A = a.asInstanceOf[A]
def compute(a: A) : A
def apply(a: Any): A = compute(cast(a))
}
case object Count extends Op[Int] {
override def compute(a: Int): Int = a + 1
}
case object Exist extends Op[Boolean] {
override def compute(a: Boolean): Boolean = a
}
object AbstractOp {
val buffer: Array[Any] = Array(42, 21, true)
val ops: Array[Op[_]] = Array(Count, Count, Exist)
def main(args: Array[String]): Unit = {
for (i <- 0 until buffer.size) {
buffer(i) = ops(i)(buffer(i))
}
println(buffer.mkString("[", ",", "]"))
}
}
Since it's asInstanceOf everywhere anyway, it does not make the code any less safe than what you had previously.
Update
If you cannot change the Op interface, then invoking cast and compute is a bit more cumbersome, but still possible:
trait Op[A] {
def cast(a: Any) : A = a.asInstanceOf[A]
def compute(a: A) : A
}
case object Count extends Op[Int] {
override def compute(a: Int): Int = a + 1
}
case object Exist extends Op[Boolean] {
override def compute(a: Boolean): Boolean = a
}
object AbstractOp {
val buffer: Array[Any] = Array(42, 21, true)
val ops: Array[Op[_]] = Array(Count, Count, Exist)
def main(args: Array[String]): Unit = {
for (i <- 0 until buffer.size) {
buffer(i) = ops(i) match {
case op: Op[t] => op.compute(op.cast(buffer(i)))
}
}
println(buffer.mkString("[", ",", "]"))
}
}
Note the ops(i) match { case op: Opt[t] => ... } part with a type-parameter in the pattern: this allows us to make sure that cast returns a t that is accepted by compute.
As a more general solution than Andrey Tyukin's, you can define the method outside Op, so it works even if Op can't be modified:
def apply[A](op: Op[A], x: Any) = op.compute(op.cast(x))
buffer(0) = apply(ops(0), buffer(0))

How to create custom assignment operator in Scala

I'm trying to create a custom data type that behaves like an Int, but has certain specific behavior and typing (eg., it has to be positive, it has to fit within the range of our database's 'integer' type, etc).
To make it a friendly class, I want to have custom assignment operators, etc., for instance I'd like the following to all work:
val g: GPID = 1 // create a GPID type with value 1
val g: GPID = 1L // take assignment from a Long (and downcast into Int)
if (g == 1) ... // test the value of GPID type against an Int(1)
This is what I have so far but I'm not getting the expected behavior:
case class GPID(value: Int) extends MappedTo[Int] {
require(value >= 1, "GPID must be a positive number")
require(value <= GPDataTypes.integer._2, s"GPID upper bound is ${GPDataTypes.integer._2}")
def this(l: Long) = this(l.toInt)
def GPID = value
def GPID_=(i: Int) = new GPID(i)
def GPID_=(l: Long) = new GPID(l.toInt)
override def toString: String = value.toString
override def hashCode:Int = value
override def equals(that: Any): Boolean =
that match {
case that: Int => this.hashCode == that.hashCode
case that: Long => this.hashCode == that.hashCode
case _ => false
}
}
object GPID {
implicit val writesGPID = new Writes[GPID] {
def writes(g: GPID): JsValue = {
Json.obj(
"GPID" -> g.value
)
}
}
implicit val reads: Reads[GPID] = (
(__ \ "GPID").read[GPID]
)
def apply(l: Long) = new GPID(l.toInt)
implicit def gpid2int(g: GPID): Int = hashCode
implicit def gpid2long(g: GPID): Long = hashCode.toLong
}
The problems I have are:
Assignment doesn't work, for instance:
val g: GPID = 1
Implicit conversion is not working, for instance:
val i: Int = g
Any help would be appreciated... haven't build a custom type like this before so overriding assignment and implicit conversion is new to me...
object TestInt extends App {
class GPID(val value: Int) {
require(value >= 1, "GPID must be a positive number")
require(value <= 10, s"GPID upper bound is 10")
override def equals(that: Any) = value.equals(that)
override def toString = value.toString
// add more methods here (pimp my library)
}
implicit def fromInt(value: Int) = new GPID(value)
implicit def fromInt(value: Long) = new GPID(value.toInt) //possible loss of precision
val g: GPID = 1
val g2: GPID = 1L
if (g == 1)
println("ONE: " + g)
else
println("NOT ONE: " + g)
}
Prints:
ONE: 1

Option method signature, function already defined in this scope

def createFloatBuffer(data: Option[Quaternion]*): Option[FloatBuffer] = data match {
...
}
def createFloatBuffer(data: Option[Vector3f]*): Option[FloatBuffer] = data match {
...
}
This code will not compile due to the two methods having the same method signature. None type would not know which method to call.
I could just rename the methods, however I would like to this overloading style in my code.
After type erasure this two methods become createFloatBuffer(data: Option), and all types information is lost and not available at run time.
As a workaround I can suggest you to use TypeClass pattern.
case class Quaternion(v: Int)
case class Vector3f(v: Int)
case class FloatBuffer(v: Int)
sealed trait FloatBufferBuilder[T] {
def createFloatBuffer(data: Option[T]): Option[FloatBuffer]
}
implicit object QuaternionFloatBufferBuilder extends FloatBufferBuilder[Quaternion] {
def createFloatBuffer(data: Option[Quaternion]) = data.map(d => FloatBuffer(d.v))
}
implicit object Vector3fFloatBufferBuilder extends FloatBufferBuilder[Vector3f] {
def createFloatBuffer(data: Option[Vector3f]) = data.map(d => FloatBuffer(d.v))
}
def createFloatBuffer[T : FloatBufferBuilder](data: Option[T]): Option[FloatBuffer] =
implicitly[FloatBufferBuilder[T]].createFloatBuffer(data)
println(createFloatBuffer(Some(Quaternion(1))))
println(createFloatBuffer(Some(Vector3f(1))))
Magnet Pattern could also interesting for you: http://spray.io/blog/2012-12-13-the-magnet-pattern/
This is the use case for:
scala> object X { def f(is: Int*) = 42 ; def f(ds: Double*) = 43 }
<console>:10: error: double definition:
def f(is: Int*): Int at line 10 and
def f(ds: Double*): Int at line 10
have same type after erasure: (is: Seq)Int
object X { def f(is: Int*) = 42 ; def f(ds: Double*) = 43 }
^
scala> object X { def f(is: Int*) = 42 ; def f(ds: Double*)(implicit dummy: DummyImplicit) = 43 }
defined object X
scala> X f 1
res2: Int = 42
scala> X f 1.0
res3: Int = 43