All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.scalautils.MapEqualityConstraints.scala Maven / Gradle / Ivy

The newest version!
/*
 * 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.scalautils

import TripleEqualsSupport._

/**
 * Provides an implicit method that loosens the equality constraint defined by TypeCheckedTripleEquals or ConversionCheckedTripleEquals
 * for Scala Maps 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 Maps, 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.scalautils._
 * import org.scalautils._
 *
 * 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.scalautils.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.scalautils.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.GenMaps 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: Constraint[KA, KB], evValue: Constraint[VA, VB]): Constraint[CA[KA, VA], 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




© 2015 - 2024 Weber Informatics LLC | Privacy Policy