Skip to content

Instantly share code, notes, and snippets.

@bvenners
Created January 17, 2014 17:47
Show Gist options
  • Save bvenners/8477980 to your computer and use it in GitHub Desktop.
Save bvenners/8477980 to your computer and use it in GitHub Desktop.
Applying ScalaUtils' tunable type checks to contains checking of Seqs.
// If you paste this code into the Scala interpretter with ScalaUtils on the path:
List(1) contains 1
List(1) contains "1"
import scala.collection.GenSeq
implicit class Containz[A](xs: GenSeq[A]) {
def containz[B <: A](ele: B): Boolean = xs.exists(_ == ele)
}
List(1) containz 1
// This now gives the desired type error
List(1) containz "1"
List(List(1)) contains Vector(1)
// But this gives an undesired type error
List(List(1)) containz Vector(1)
// So will need to use an implicit constraint instead
import org.scalautils._
import TypeCheckedTripleEquals._
import TraversableEqualityConstraints._
implicit class Containz[A](xs: GenSeq[A]) {
def containz[B](ele: B)(implicit ev: Constraint[A, B]): Boolean = xs.exists(ev.areEqual(_, ele))
}
// Now the compiler allows this, as desired
List(1) containz 1
// This fails to compile, as desired
List(1) containz "1"
// But the compiler also allows this, as desired
List(List(1)) containz Vector(1)
// It won't allow this to compile, which is "desired" because it returns true:
List(1) containz BigInt(1)
// But I can get that to work another implicit constraint, which I'll likely
// add to ScalaUtils now that I am aware of this cooperative
// equality behavior among Numeric types.
You will see this output:
scala> List(1) contains 1
res0: Boolean = true
scala> List(1) contains "1"
res1: Boolean = false
scala>
scala> import scala.collection.GenSeq
import scala.collection.GenSeq
scala> implicit class Containz[A](xs: GenSeq[A]) {
| def containz[B <: A](ele: B): Boolean = xs.exists(_ == ele)
| }
defined class Containz
scala>
scala> List(1) containz 1
res2: Boolean = true
scala> // This now gives the desired type error
scala> List(1) containz "1"
<console>:10: error: inferred type arguments [String] do not conform to method containz's type parameter bounds [B <: Int]
List(1) containz "1"
^
<console>:10: error: type mismatch;
found : String("1")
required: B
List(1) containz "1"
^
scala>
scala> List(List(1)) contains Vector(1)
res4: Boolean = true
scala> // But this gives an undesired type error
scala> List(List(1)) containz Vector(1)
<console>:10: error: inferred type arguments [scala.collection.immutable.Vector[Int]] do not conform to method containz's type parameter bounds [B <: List[Int]]
List(List(1)) containz Vector(1)
^
<console>:10: error: type mismatch;
found : scala.collection.immutable.Vector[Int]
required: B
List(List(1)) containz Vector(1)
^
scala>
scala> // So will need to use an implicit constraint instead
scala> import org.scalautils._
import org.scalautils._
scala> import TypeCheckedTripleEquals._
import TypeCheckedTripleEquals._
scala> import TraversableEqualityConstraints._
import TraversableEqualityConstraints._
scala>
scala> implicit class Containz[A](xs: GenSeq[A]) {
| def containz[B](ele: B)(implicit ev: Constraint[A, B]): Boolean = xs.exists(ev.areEqual(_, ele))
| }
defined class Containz
scala>
scala> // Now the compiler allows this, as desired
scala> List(1) containz 1
res6: Boolean = true
scala>
scala> // This fails to compile, as desired
scala> List(1) containz "1"
<console>:20: error: types Int and String do not adhere to the type constraint selected for the === and !== operators; the missing implicit parameter is of type org.scalautils.Constraint[Int,String]
List(1) containz "1"
^
scala>
scala> // But the compiler also allows this, as desired
scala> List(List(1)) containz Vector(1)
res8: Boolean = true
scala>
scala> // It won't allow this to compile, which is "desired" because it returns true:
scala> List(1) containz BigInt(1)
<console>:20: error: types Int and scala.math.BigInt do not adhere to the type constraint selected for the === and !== operators; the missing implicit parameter is of type org.scalautils.Constraint[Int,scala.math.BigInt]
List(1) containz BigInt(1)
^
scala>
scala> // But I can get that to work another implicit constraint, which I'll likely
scala> // add to ScalaUtils now that I am aware of this cooperative
scala> // equality behavior among Numeric types.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment