Equals for case class with floating point fields - scala

Is it ok, to create case classes with floating point fields, like:
case class SomeClass(a:Double, b:Double)
I guess auto generated equal method won't work in this case.
Is overriding equals the best solution?
EDIT:
if overriding equals is the way to go, I would like to avoid hardcoding epsilon ( where epsilon is defined like => |this.a-a|< epsilon). This won't compile:
case class SomeClass(a:Double, b:Double, implicit epsilon:Double)
I am looking for a way to pass epsilon without passing concert value each time
(some "implicit" magic).
I have also follow up more general question, how would you define hashcode for class with only floating point fields?

You are correct. If you are worried about precision, then you will need to override equals:
case class SomeClass(a:Double, b:Double)
SomeClass(2.2 * 3, 1.0) == SomeClass(6.6, 1.0)
// res0: Boolean = false
case class BetterClass(a: Double, b: Double) {
override def equals(obj: Any) = obj match {
case x: BetterClass =>
(this.a - x.a).abs < 0.0001 && (this.b - x.b).abs < 0.0001
case _ => false
}
}
BetterClass(2.2 * 3, 1.0) == BetterClass(6.6, 1.0)
// res1: Boolean = true

Ah, the joy of floating point numbers.
I think it is not a good idea to override equals with a fuzzy comparison. It violates all sorts of things that you usually take for granted with equality. Imagine a, b and c are some case classes with a fuzzy equals. Then it is possible to have a, b, c such that a==b, b==c but a!=c.
Then there is the behavior of hashcode to consider. If you override equals with fuzzy equality and do not override hashcode, you will not be able to use the resulting object in a hashmap or set, because a==b but a.hashcode!=b.hashcode.
The best way to solve the problem is to define an operator like =~= that provides a fuzzy comparison in addition to equals/== which (at least for immutable objects in scala) means that objects are exactly identical so that you can replace one with the other without changing the result of a calculation.
If you also want the ability to configure the precision of the comparison via an implicit, that adds another level of complexity. Here is a more complete example:
// a class to configure the comparison that will be passed to the operator
// as an implicit value
case class CompareSettings(epsilon:Double = 0.1) extends AnyVal
// add an operator =~= to double to do a fuzzy comparions
implicit class DoubleCompareExtensions(val value:Double) extends AnyVal {
def =~=(that:Double)(implicit settings:CompareSettings) : Boolean = {
// this is not a good way to do a fuzzy comparison. You should have both relative
// and absolute precision. But for an example like this it should suffice.
(value - that).abs < settings.epsilon
}
}
case class SomeClass(x:Double, y:Double) {
// we need an implicit argument of type CompareSettings
def =~=(that:SomeClass)(implicit settings:CompareSettings) =
// the implicit argument will be automatically passed on to the operators
this.x =~= that.x && this.y =~= that.y
}
// usage example
val x=1.0
val y=1.01
// this won't work since there is no implicit in scope
x =~= y
// define an implicit of the right type
implicit val compareSettings = CompareSettings(0.2)
// now this will work
x =~= y
// and this as well
SomeClass(1,2) =~= SomeClass(1.1,2)
Note that the implicit is not an argument of the class but of the operation.

Related

How `set.contains` works in Scala?

Consider the following code:
import scala.collection.mutable
case class A(b: Int) {
override def equals(obj: Any): Boolean = {
println("called")
obj match {
case o: A => b == o.b
case _ => false
}
}
}
val set = mutable.Set.empty[A]
val a1 = A(1)
set.add(a1)
println(set.contains(A(1)))
println(set.contains(A(2)))
Why the second call of set.contains doesn't print out "called"? Can someone explain how set identify two objects being equal?
As #LuisMiguelMejíaSuárez mentioned in the comments, A mutable Set is backed by a HashSet. It is well elaborated at What issues should be considered when overriding equals and hashCode in Java?
Whenever a.equals(b), then a.hashCode() must be same as b.hashCode().
This is because hashCode is a prior check, which when fails equals will definitely fail as well.
From What code is generated for an equals/hashCode method of a case class? we can conclude that for case classes hashCode and equals are overridden for case classes, using productPrefix which means the first set of elements in the case class. For example, if we have:
case class c(a: A)(b: B)
The hashCode and equals will be calculated only based on a. In your case, the hasCode method is calculated based on gender, which is different for Person(1) and Person(2). Therefore there is no need to check equals, which suppose to fail as well.
A tip from What issues should be considered when overriding equals and hashCode in Java?
In practice:
If you override one, then you should override the other.
Use the same set of fields that you use to compute equals() to compute hashCode().

Encapsulate companion boilerplate behind annotation+macro

I'm using ADTs that should only be able to be constructed after a validation step (which is common practice in FP to ensure correctness). As an example, I'm using a Score type on top of Double, which validates its wrapped value to be within [0.0, 100.0].
So I have something like this:
case class Score private(raw: Double) extends AnyVal
object Score {
def mk(raw: Double) = (0 <= raw && raw <= 100) option new Score(raw)
// XXX: WOULD LIKE TO GET RID OF THIS LINE:
def apply(raw: Double)(implicit ev: DummyImplicit): Score = ???
}
It's a workaround to it not being possible to hide the auto-generated case class companion apply taken from this answer https://stackoverflow.com/a/5736428/247623 to a completely unrelated question.
Whereas it works to a satisfactory extent — except for the compilation error ambiguous reference to overloaded definition not at all being helpful — it has the huge downside of the definition of each ADT with a guarded constructor having to explicitly define this:
def apply(raw: Double)(implicit ev: Nothing): Score = notAllowed
I've tried using inheritance to no avail.
Is it at all possible to achieve this using macros or do Scala macros not currently support adding of methods to a class/object? Something like:
case class Score private(raw: Double) extends AnyVal
#guarded object Score {
def mk(raw: Double) = (0 <= raw && raw <= 100) option new Score(raw)
}
...or similar.

Scala match class exactly (not extends)

Question
In Scala, is there a way to write a match clause which matches an object by it's class, but does not match any extending classes?
Motivation
It may seem pedantic.. it is.
Anyway, I thought of it when I saw the equals function generated by IntelliJ:
class Position(val x: Float, val y: Float) {
def canEqual(other: Any): Boolean = other.isInstanceOf[Position]
override def equals(other: Any): Boolean = other match {
case that: Position =>
(that canEqual this) &&
x == that.x &&
y == that.y
case _ => false
}
// generated hashCode omitted for brevity
}
Here we can see that other is class matched to be a Position, and then canEqual is used to put an upper bound on the match. That is, other could still be, say, a Position3D, which shouldn't equal a Position even if the x and y coordinates are the same.
This makes sense, but I wonder if some form of Scala wizardry would let us explicitly match Position classes and not subclasses.
There's a reason the auto-generated equals method doesn't do what you're suggesting. The canEqual convention is a common and well-documented one, because it allows for handling a broader set of common use cases.
You don't always want to exclude all sub classes when implementing an equals method, only ones that override equals. If, as you described, there was a Position3D class extending Position, and Position3D had an additional field z that was part of the Position3D equals method, then of course that Position3D should not be equal to any normal 2D position.
But what if for some reason a user wants to instantiate an anonymous subclass of Position?
val pos = new Position(1,2){}
or
trait Foo
val pos = new Position(1,2) with Foo
This position should probably be considered equal to new Position(1,2). Disallowing this equality could in some situations be tedious, if the mixed-in functionality is trivial or just for some particular local-scope use case. To require, as the other response suggested, other.getClass == classOf[Position], a client API mixing in a trait or for some reason creating an anonymous class might find they're creating positions that are not even equal to themselves.
Consider this code:
class Position(val x:Int, val y:Int) {
override def equals(other:Any) = other match {
case o:Position if o.getClass==classOf[Position] && o.x==x && o.y==y => true
case _ => false
}
}
trait Foo
val p1 = new Position(1,2) with Foo
val p2 = new Position(1,2) with Foo
p1 == p2
the result is false
see:
http://www.artima.com/lejava/articles/equality.html
Try:
other match {
case that: Position if that.getClass == classOf[Postion] => // or just getClass
(that canEqual this) &&
x == that.x &&
y == that.y
case: that: Postion => false //this case can be removed
case _ => false
}

How can I define a custom equality operation that will be used by immutable Set comparison methods

I have an immutable Set of a class, Set[MyClass], and I want to use the Set methods intersect and diff, but I want them to test for equality using my custom equals method, rather than default object equality test
I have tried overriding the == operator, but it isn't being used.
Thanks in advance.
Edit:
The intersect method is a concrete value member of GenSetLike
spec: http://www.scala-lang.org/api/current/scala/collection/GenSetLike.html
src: https://lampsvn.epfl.ch/trac/scala/browser/scala/tags/R_2_9_1_final/src//library/scala/collection/GenSetLike.scala#L1
def intersect(that: GenSet[A]): Repr = this filter that
so the intersection is done using the filter method.
Yet another Edit:
filter is defined in TraversableLike
spec: http://www.scala-lang.org/api/current/scala/collection/TraversableLike.html
src: https://lampsvn.epfl.ch/trac/scala/browser/scala/tags/R_2_9_1_final/src//library/scala/collection/TraversableLike.scala#L1
def filter(p: A => Boolean): Repr = {
val b = newBuilder
for (x <- this)
if (p(x)) b += x
b.result
}
What's unclear to me is what it uses when invoked without a predicate, p. That's not an implicit parameter.
equals and hashCode are provided automatically in case class only if you do not define them.
case class MyClass(val name: String) {
override def equals(o: Any) = o match {
case that: MyClass => that.name.equalsIgnoreCase(this.name)
case _ => false
}
override def hashCode = name.toUpperCase.hashCode
}
Set(MyClass("xx"), MyClass("XY"), MyClass("xX"))
res1: scala.collection.immutable.Set[MyClass] = Set(MyClass(xx), MyClass(XY))
If what you want is reference equality, still write equals and hashCode, to prevent automatic generation, and call the version from AnyRef
override def equals(o: Any) = super.equals(o)
override def hashCode = super.hashCode
With that:
Set(MyClass("x"), MyClass("x"))
res2: scala.collection.immutable.Set[MyClass] = Set(MyClass(x), MyClass(x))
You cannot override the ==(o: Any) from AnyRef, which is sealed and always calls equals. If you tried defining a new (overloaded) ==(m: MyClass), it is not the one that Set calls, so it is useless here and quite dangerous in general.
As for the call to filter, the reason it works is that Set[A] is a Function[A, Boolean]. And yes, equals is used, you will see that function implementation (apply) is a synonymous for contains, and most implementations of Set use == in contains (SortedSet uses the Ordering instead). And == calls equals.
Note: the implementation of my first equals is quick and dirty and probably bad if MyClass is to be subclassed . If so, you should at the very least check type equality (this.getClass == that.getClass) or better define a canEqual method (you may read this blog by Daniel Sobral)
You'll need to override .hashCode as well. This is almost always the case when you override .equals, as .hashCode is often used as a cheaper pre-check for .equals; any two objects which are equal must have identical hash codes. I'm guessing you're using objects whose default hashCode does not respect this property with respect to your custom equality, and the Set implementation is making assumptions based on the hash codes (and so never even calling your equality operation).
See the Scala docs for Any.equals and Any.hashCode: http://www.scala-lang.org/api/rc/scala/Any.html
This answer shows a custom mutable Set with user-defined Equality. It could be made immutable by replacing the internal store with a Vector and returning a modified copy of itself upon each operation
"It is not possible to override == directly, as it is defined as a final method in class Any. That is, Scala treats == as if were defined as follows in class Any:
final def == (that: Any): Boolean =
if (null eq this) {null eq that} else {this equals that}
" from Programming In Scala, Second Edition

Writing a generic mean function in Scala

I'm trying to write a generic mean function that operates on an Iterable that contains numeric types. It would operate, say, on arrays, as so:
val rand = new scala.util.Random()
val a = Array.fill(1000) { rand.nextInt(101) }
val b = Array.fill(1000) { rand.nextDouble }
println(mean(a))
println(mean(b))
etc., hopefully being able to work on other iterables, such as lists.
I have tried various incantations for the mean method, to no avail:
def mean[T <% Numeric[T]](xs: Iterable[T]) = xs.sum.toDouble / xs.size
def mean[A](xs: Iterable[Numeric[A]]):Double = xs.sum.toDouble / xs.size
def mean[T](xs: Iterable[T])(implicit num: Numeric[T]):Double = xs.sum / xs.size
def mean(xs: Iterable[Double]) = xs.sum / xs.size
What is the proper way to do this in Scala?
This works:
def mean[T : Numeric](xs: Iterable[T]): T = implicitly[Numeric[T]] match {
case num: Fractional[_] => import num._; xs.sum / fromInt(xs.size)
case num: Integral[_] => import num._; xs.sum / fromInt(xs.size)
case _ => sys.error("Undivisable numeric!")
}
So, let's make some explanations. First, Numeric must be used in type class pattern. That is, you don't say a type T is, or can be converted into, Numeric. Instead, Numeric provides methods over a type T. One such example is num.fromInt.
Next, Numeric does not provide a common division operator. Instead, one must choose between Fractional and Integral. Here, I'm matching on Numeric[T] to distinguish between both.
Note that I don't use T on the match, because Scala cannot check for type parameters on matches, as they are erased. Instead, I use _, and Scala infers the correct type if possible (as it is here).
After that, I'm importing num._, where num is either Fractional or Integral. This brings some implicit conversions into context that let me do stuff like calling the method / directly. If I did not do that import, I'd be forced to write this:
num.div(xs.sum, num.fromInt(xs.size))
Note that I do not have to pass the implicit parameter to xs.sum, since it is already implicitly available in the scope.
I guess that's it. Did I miss anything?
One of your version is pretty close:
def mean[T](xs: Iterable[T])(implicit num: Numeric[T]):Double =
num.toDouble(xs.sum) / xs.size
Here is the other syntax:
def mean[T: Numeric](xs: Iterable[T]):Double =
implicitly[Numeric[T]].toDouble(xs.sum) / xs.size
def mean[A](it:Iterable[A])(implicit n:Numeric[A]) = {
it.map(n.toDouble).sum / it.size
}
This is quite an old question, but I am basically doing this
def average[A](list: List[Any])(implicit numerics: Numeric[A]): Double = {
list.map(Option(_)).filter(_.isDefined).flatten match {
case Nil => 0.0
case definedElements => numerics.toDouble(list.map(_.asInstanceOf[A]).sum) / definedElements.length.toDouble
}
}
for a list which might contain null values (I have to keep interoperability with Java). The null elements are not counted towards the average.