org.scalactic.MapEqualityConstraints.scala Maven / Gradle / Ivy
/*
* Copyright 2001-2013 Artima, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.scalactic
import TripleEqualsSupport._
/**
* Provides an implicit method that loosens the equality constraint defined by TypeCheckedTripleEquals
or ConversionCheckedTripleEquals
* for Scala Map
s to one that more closely matches Scala's approach to Map
equality.
*
*
* Scala's approach to Map
equality is that if both objects being compared are Map
s, the elements are compared to determine equality.
* This means you could compare an immutable TreeMap
and a mutable HashMap
for equality, for instance, and get true so long as the two maps
* contained the same key-value mappings. Here's an example:
*
*
*
* scala> import scala.collection.immutable.TreeMap
* import scala.collection.immutable.TreeMap
*
* scala> import scala.collection.mutable.HashMap
* import scala.collection.mutable.HashMap
*
* scala> TreeMap("one" -> 1, "two" -> 2) == HashMap("one" -> 1, "two" -> 2)
* res0: Boolean = true
*
*
*
* Such a comparison would not, however, compile if you used ===
under either TypeCheckedTripleEquals
or ConversionCheckedTripleEquals
,
* because TreeMap
and HashMap
are not in a subtype/supertype relationship, nor does an implicit conversion by default exist between them:
*
*
*
* scala> import org.scalactic._
* import org.scalactic._
*
* scala> import TypeCheckedTripleEquals._
* import TypeCheckedTripleEquals._
*
* scala> TreeMap("one" -> 1, "two" -> 2) === HashMap("one" -> 1, "two" -> 2)
* <console>:16: error: types scala.collection.immutable.TreeMap[String,Int] and
* scala.collection.mutable.HashMap[String,Int] do not adhere to the equality constraint selected for
* the === and !== operators; the missing implicit parameter is of type
* org.scalactic.EqualityConstraint[scala.collection.immutable.TreeMap[String,Int],
* scala.collection.mutable.HashMap[String,Int]]
* TreeMap("one" -> 1, "two" -> 2) === HashMap("one" -> 1, "two" -> 2)
* ^
*
*
*
* If you mix or import the implicit conversion provided by MapEqualityConstraint
, however, the comparison will be allowed:
*
*
*
* scala> import MapEqualityConstraints._
* import MapEqualityConstraints._
*
* scala> TreeMap("one" -> 1, "two" -> 2) === HashMap("one" -> 1, "two" -> 2)
* res2: Boolean = true
*
*
*
* The equality constraint provided by this trait requires that both left and right sides are subclasses of scala.collection.GenMap
and that
* an EqualityConstraint
can be found for both key types and both value types. In the example above, both the TreeMap
and
* HashMap
are subclasses of scala.collection.GenMap
, and the regular TypeCheckedTripleEquals
provides equality
* constraints for the key types, both of which are String
, and value types, both of which are Int
. By contrast, this
* trait would not allow a TreeMap[String, Int]
to be compared against a HashMap[String, java.util.Date]
, because no equality constraint
* will exist between the value types Int
and Date
:
*
*
*
* scala> import java.util.Date
* import java.util.Date
*
* scala> TreeMap("one" -> 1, "two" -> 2) === HashMap("one" -> new Date, "two" -> new Date)
* <console>:20: error: types scala.collection.immutable.TreeMap[String,Int] and
* scala.collection.mutable.HashMap[String,java.util.Date] do not adhere to the equality constraint selected for
* the === and !== operators; the missing implicit parameter is of type
* org.scalactic.EqualityConstraint[scala.collection.immutable.TreeMap[String,Int],
* scala.collection.mutable.HashMap[String,java.util.Date]]
* TreeMap("one" -> 1, "two" -> 2) === HashMap("one" -> new Date, "two" -> new Date)
* ^
*
*
* @author Bill Venners
*/
trait MapEqualityConstraints {
import scala.language.higherKinds
/**
* Provides an equality constraint that allows two subtypes of scala.collection.GenMap
s to be compared for equality with ===
so long
* as an EqualityConstraint
is available for both key types and both value types.
*/
implicit def mapEqualityConstraint[KA, VA, CA[ka, kb] <: collection.GenMap[ka, kb], KB, VB, CB[kb, vb] <: collection.GenMap[kb, vb]](implicit equalityOfA: Equality[CA[KA, VA]], evKey: KA CanEqual KB, evValue: VA CanEqual VB): CA[KA, VA] CanEqual CB[KB, VB] = new EqualityConstraint[CA[KA, VA], CB[KB, VB]](equalityOfA)
}
/**
* Companion object that facilitates the importing of MapEqualityConstraints
members as
* an alternative to mixing it in. One use case is to import MapEqualityConstraints
members so you can use
* them in the Scala interpreter.
*/
object MapEqualityConstraints extends MapEqualityConstraints