SlideShare une entreprise Scribd logo
1  sur  24
Télécharger pour lire hors ligne
Equality For All!
Scala by the Bay, 2014
BillVenners
Artima, Inc.
Escalate Software
Saturday, August 9, 2014
Equality: An equivalence relation with
one element per equivalence class
42 4341
42 = 4241 = 41 43 = 43
reflexive: x = x
symmetric: x = y iff y = x
transitive: if x = y and y = z then x = z
Saturday, August 9, 2014
How do I say forty two in code?
Let me count the ways...
42
42L
42.0
42.0F
42.toShort
'*'
42.toByte BigInt(42)
BigDecimal(42)
new java.lang.Integer(42)
new java.lang.Long(42L)
new java.lang.Double(42.0)
new java.lang.Float(42.0F) new java.lang.Short(42.toShort)
new java.lang.Character(42)
new java.lang.Byte(42.toByte)
new java.math.BigInteger("42")
new java.math.BigDecimal(42) Complex(42.0, 0.0)
DigitString("42") DigitString("042")
Saturday, August 9, 2014
The equals method implements an equivalence relation on non-null object references:
• It is reflexive: for any non-null reference value x, x.equals(x) should return true.
• It is symmetric: for any non-null reference values x and y, x.equals(y) should return true
if and only if y.equals(x) returns true.
• It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true
and y.equals(z) returns true, then x.equals(z) should return true.
• It is consistent: for any non-null reference values x and y, multiple invocations of
x.equals(y) consistently return true or consistently return false, provided no
information used in equals comparisons on the objects is modified.
• For any non-null reference value x, x.equals(null) should return false.
Java's equals contract
public boolean equals(Object obj)
final def == (other:Any): Boolean
Saturday, August 9, 2014
scala> 42 == 42L
res0: Boolean = true
scala> BigDecimal(42) == '*'
res1: Boolean = true
scala> 42.0F == BigInt(42)
res2: Boolean = true
scala> new java.lang.Float(42.0F) == 42.toShort
res3: Boolean = true
Co-operative Equality Between Types
Saturday, August 9, 2014
scala> import scala.collection.mutable
import scala.collection.mutable
scala> Set(BigInt(4), BigInt(2)) == mutable.Set(4.toByte,
2.toByte)
res4: Boolean = true
scala> Vector(Left(4), Right(2)) == List(Left(4L), Right(2L))
res5: Boolean = true
scala> List(mutable.Set(Map(Some(4L) -> BigInt(2)))) ==
Vector(Set(mutable.Map(Some(4.0) -> new java.lang.Long(2L))))
res6: Boolean = true
Co-operative Equality Between Types
Saturday, August 9, 2014
scala> Array(4, 2) == Array(4, 2)
res7: Boolean = false
scala> <forty><two></two></forty> == <forty> <two></two> </forty>
res8: Boolean = false
scala> new java.math.BigDecimal("42.0") ==
new java.math.BigDecimal("42.00")
res9: Boolean = false
scala> 42.0 == 41.9999999999
res10: Boolean = false
scala> "case" == "CASE"
res11: Boolean = false
Wanted: Alternate equalities
Saturday, August 9, 2014
scala> "forty two" == 42
res19: Boolean = false
scala> List(mutable.Set(Map(Some(4L) -> BigInt(2)))) ==
Vector(Set(mutable.Map(Some("4.0") -> new java.lang.Long(2L))))
res23: Boolean = false
Wanted: Type errors
But how to decide which comparisons compile?
Saturday, August 9, 2014
scala> "forty two" == 42
<console>:20: error: types String and Int do not adhere to the
type constraint selected for the === and !== operators; the
missing implicit parameter is of type
org.scalactic.EqualityConstraint[String,Int]
"forty two" === 42
^
scala> BigInt(42) === BigDecimal(42)
res1: Boolean = true
Fail to compile if L can never equal R.
Saturday, August 9, 2014
scala> Vector.empty === List.empty
<console>:20: error: ambiguous implicit values:
both method conflictingEmptySeqConstraint1 in object EqualityConstraint of type [LSEQ[e] <:
scala.collection.GenSeq[e], RSEQ[e] <: scala.collection.GenSeq[e]]=>
org.scalactic.EqualityConstraint[LSEQ[Nothing],RSEQ[Nothing]]
and method conflictingEmptySeqConstraint2 in object EqualityConstraint of type [LSEQ[e] <:
scala.collection.GenSeq[e], RSEQ[e] <: scala.collection.GenSeq[e]]=>
org.scalactic.EqualityConstraint[LSEQ[Nothing],RSEQ[Nothing]]
match expected type
org.scalactic.EqualityConstraint[scala.collection.immutable.Vector[A],List[Nothing]]
Vector.empty === List.empty
^
scala> Vector.empty === List.empty[Int]
res3: Boolean = true
scala> Vector.empty[String] === List.empty
res4: Boolean = true
Fail to compile if L will always equal R.
Saturday, August 9, 2014
Candidate rule:
To compile, an equality comparison
must be interesting: values of types L
and R can be either equal or unequal.
Saturday, August 9, 2014
scala> case class Complex(real: Double, imaginary: Double)
defined class Complex
scala> implicit def convertIntToComplex(i: Int): Complex = Complex(i, 0.0)
convertIntToComplex: (i: Int)Complex
scala> 42 === Complex(42, 0)
<console>:24: error: types Int and Complex do not adhere to the type constraint selected for the
=== and !== operators; the missing implicit parameter is of type
org.scalactic.EqualityConstraint[Int,Complex]
42 === Complex(42, 0)
^
scala> Complex(42, 0) === 42
<console>:24: error: types Complex and Int do not adhere to the type constraint selected for the
=== and !== operators; the missing implicit parameter is of type
org.scalactic.EqualityConstraint[Complex,Int]
Complex(42, 0) === 42
^
What about implicit conversions?
Saturday, August 9, 2014
scala> implicit val enabler = EqualityEnabledBetween[Int, Complex]
enabler: org.scalactic.EqualityEnabledBetween[Int,Complex] =
org.scalactic.EqualityEnabledBetween@e5d2d9b
scala> 42 === Complex(42, 0)
res2: Boolean = true
scala> Complex(42, 0) === 42
res3: Boolean = true
scala> new AnyShouldWrapper(1) === 1 // Probably shouldn't enable...
Intuition: enable some but not all
But what would the rule be?
Saturday, August 9, 2014
OK if the conversion is an injection
scala> case class DigitString(digits: String) {
| val toInt: Int = digits.toInt
| }
defined class DigitString
scala> implicit def convert(d: DigitString): Int =
| d.digits.toInt
convertDigitStringToInt: (d: DigitString)Int
scala> DigitString("42") === DigitString("042")
res0: Boolean = false
scala> DigitString("42").toInt === DigitString("042").toInt
res1: Boolean = true
John C. Reynolds: Using category theory to design implicit conversions and generic operators.
Saturday, August 9, 2014
How to decide:
1.To compile, an equality comparison must be
interesting: values of types L and R can be either
equal or unequal.
2.Allow select implicit conversions to be enabled,
and recommend that non-widening conversions
(non-injections) not be enabled.
Saturday, August 9, 2014
scala> (Some(1): Option[Int]) === Some(1)
res0: Boolean = true
scala> Some(1) === (Some(1): Option[Int])
res1: Boolean = true
scala> Some(1) === Some(1)
res2: Boolean = true
What about the implicit conversion
from subtype to supertype (<:<)?
Saturday, August 9, 2014
scala> def eqv[T](a: T, b: T): Boolean = a === b
eqv: [T](a: T, b: T)Boolean
scala> eqv(1, ())
res3: Boolean = false
scala> ((i: Int) => i + 1) === ((i: Int) => i + 1)
res4: Boolean = false
Even though <:< is an injection, is it
always desireable?
Saturday, August 9, 2014
EqualityPolicy
UncheckedEquality CheckedEquality EnabledEquality
Saturday, August 9, 2014
scala> import EnabledEquality._
import EnabledEquality._
scala> def eqv[T](a: T, b: T): Boolean = a === b
<console>:19: error: types T and T do not adhere to the type constraint selected for
the === and !== operators; the missing implicit parameter is of type
org.scalactic.EqualityConstraint[T,T]
def eqv[T](a: T, b: T): Boolean = a === b
^
scala> ((i: Int) => i + 1) === ((i: Int) => i + 1)
<console>:20: error: types Int => Int and Int => Int do not adhere to the type
constraint selected for the === and !== operators; the missing implicit parameter is
of type org.scalactic.EqualityConstraint[Int => Int,Int => Int]
((i: Int) => i + 1) === ((i: Int) => i + 1)
^
EnabledEquality benefit
Saturday, August 9, 2014
scala> case class Person(name: String)
defined class Person
scala> Person("Sue") === Person("Sue")
<console>:22: error: types Person and Person do not adhere to the type constraint
selected for the === and !== operators; the missing implicit parameter is of type
org.scalactic.EqualityConstraint[Person,Person]
Person("Sue") === Person("Sue")
^
scala> implicit val enabler = new EqualityEnabledFor[Person]
enabler: org.scalactic.EqualityEnabledFor[Person] =
org.scalactic.EqualityEnabledFor@1289d391
scala> Person("Sue") === Person("Sue")
res2: Boolean = true
EnabledEquality cost
Saturday, August 9, 2014
scala> 1 should === ("one")
<console>:23: 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.scalactic.Constraint[Int,String]
1 should === ("one")
^
scala> 1 should equal ("one")
<console>:23: error: could not find implicit value for parameter typeClass1:
org.scalactic.enablers.EvidenceThat[String]#CanEqual[Int]
1 should equal ("one")
^
scala> 1 should be ("one")
<console>:23: error: could not find implicit value for parameter typeClass1:
org.scalactic.enablers.EvidenceThat[String]#CanEqual[Int]
1 should be ("one")
^
scala> 1 should be_== ("one")
org.scalatest.exceptions.TestFailedException: 1 was not equal to "one"
ScalaTest's equal, be, and be_==
Saturday, August 9, 2014
scala> List(1, 2, 3) should contain ("one")
<console>:23: error: could not find implicit value for parameter typeClass1:
org.scalactic.enablers.EvidenceThat[String]#CanBeContainedIn[List[Int]]
List(1, 2, 3) should contain ("one")
^
scala> List(1, 2, 3) should contain oneOf ("one", "two")
<console>:23: error: could not find implicit value for parameter evidence:
org.scalactic.enablers.EvidenceThat[String]#CanBeContainedIn[List[Int]]
List(1, 2, 3) should contain oneOf("one", "two")
^
scala> 1 isIn List(1, 2, 3)
res14: Boolean = true
scala> "one" isIn List(1, 2, 3)
<console>:23: error: Could not find evidence that String can be contained in List[Int]; the missing implicit
parameter is of type org.scalactic.enablers.ContainingConstraint[List[Int],String]
"one" isIn List(1, 2, 3)
^
ScalaTest's contain, Scalactic's isIn/isNotIn
Saturday, August 9, 2014
if sufficientTimeRemains then (Q => A) else thanks
artima.com/shop
15% discount
coupon code:
BYTHEBAY2014
Saturday, August 9, 2014
scala> 1L === 1
res0: Boolean = true
scala> 1 === 1L
<console>:14: error: could not find implicit value for parameter F0:
scalaz.Equal[Any]
1 === 1L
^
Scalaz or Spire
Scalactic
scala> 1L === 1
res7: Boolean = true
scala> 1 === 1L
res8: Boolean = true
Equal[T], Eq[T]
EqualityConstraint[L, R]
Equivalence[T]
Saturday, August 9, 2014

Contenu connexe

Tendances

Effective way to code in Scala
Effective way to code in ScalaEffective way to code in Scala
Effective way to code in ScalaKnoldus Inc.
 
5-minute intro to property-based testing in Python with hypothesis
5-minute intro to property-based testing in Python with hypothesis5-minute intro to property-based testing in Python with hypothesis
5-minute intro to property-based testing in Python with hypothesisFranklin Chen
 
ECET 370 HELPS Redefined Education--ecet370helps.com
ECET 370 HELPS Redefined Education--ecet370helps.comECET 370 HELPS Redefined Education--ecet370helps.com
ECET 370 HELPS Redefined Education--ecet370helps.comGVlaxmi7
 
Programming in Scala: Notes
Programming in Scala: NotesProgramming in Scala: Notes
Programming in Scala: NotesRoberto Casadei
 
Scala case of case classes
Scala   case of case classesScala   case of case classes
Scala case of case classesVulcanMinds
 
Getting Started With Scala
Getting Started With ScalaGetting Started With Scala
Getting Started With ScalaMeetu Maltiar
 
Taxonomy of Scala
Taxonomy of ScalaTaxonomy of Scala
Taxonomy of Scalashinolajla
 
Hello, Guava !
Hello, Guava !Hello, Guava !
Hello, Guava !輝 子安
 
Lecture 5: Functional Programming
Lecture 5: Functional ProgrammingLecture 5: Functional Programming
Lecture 5: Functional ProgrammingEelco Visser
 
RubyMiniGuide-v1.0_0
RubyMiniGuide-v1.0_0RubyMiniGuide-v1.0_0
RubyMiniGuide-v1.0_0tutorialsruby
 
Demystifying functional programming with Scala
Demystifying functional programming with ScalaDemystifying functional programming with Scala
Demystifying functional programming with ScalaDenis
 
Functional programming in Scala
Functional programming in ScalaFunctional programming in Scala
Functional programming in ScalaDamian Jureczko
 
Property based Testing - generative data & executable domain rules
Property based Testing - generative data & executable domain rulesProperty based Testing - generative data & executable domain rules
Property based Testing - generative data & executable domain rulesDebasish Ghosh
 
Scala collections api expressivity and brevity upgrade from java
Scala collections api  expressivity and brevity upgrade from javaScala collections api  expressivity and brevity upgrade from java
Scala collections api expressivity and brevity upgrade from javaIndicThreads
 
Introduction to programming in scala
Introduction to programming in scalaIntroduction to programming in scala
Introduction to programming in scalaAmuhinda Hungai
 
Programming in Scala - Lecture Four
Programming in Scala - Lecture FourProgramming in Scala - Lecture Four
Programming in Scala - Lecture FourAngelo Corsaro
 

Tendances (20)

Effective way to code in Scala
Effective way to code in ScalaEffective way to code in Scala
Effective way to code in Scala
 
Chapter3
Chapter3Chapter3
Chapter3
 
5-minute intro to property-based testing in Python with hypothesis
5-minute intro to property-based testing in Python with hypothesis5-minute intro to property-based testing in Python with hypothesis
5-minute intro to property-based testing in Python with hypothesis
 
ECET 370 HELPS Redefined Education--ecet370helps.com
ECET 370 HELPS Redefined Education--ecet370helps.comECET 370 HELPS Redefined Education--ecet370helps.com
ECET 370 HELPS Redefined Education--ecet370helps.com
 
Collections
CollectionsCollections
Collections
 
Programming in Scala: Notes
Programming in Scala: NotesProgramming in Scala: Notes
Programming in Scala: Notes
 
Scala case of case classes
Scala   case of case classesScala   case of case classes
Scala case of case classes
 
Getting Started With Scala
Getting Started With ScalaGetting Started With Scala
Getting Started With Scala
 
Taxonomy of Scala
Taxonomy of ScalaTaxonomy of Scala
Taxonomy of Scala
 
Hello, Guava !
Hello, Guava !Hello, Guava !
Hello, Guava !
 
Lecture 5: Functional Programming
Lecture 5: Functional ProgrammingLecture 5: Functional Programming
Lecture 5: Functional Programming
 
RubyMiniGuide-v1.0_0
RubyMiniGuide-v1.0_0RubyMiniGuide-v1.0_0
RubyMiniGuide-v1.0_0
 
Demystifying functional programming with Scala
Demystifying functional programming with ScalaDemystifying functional programming with Scala
Demystifying functional programming with Scala
 
Scala for curious
Scala for curiousScala for curious
Scala for curious
 
Functional programming in Scala
Functional programming in ScalaFunctional programming in Scala
Functional programming in Scala
 
Property based Testing - generative data & executable domain rules
Property based Testing - generative data & executable domain rulesProperty based Testing - generative data & executable domain rules
Property based Testing - generative data & executable domain rules
 
Scala collections api expressivity and brevity upgrade from java
Scala collections api  expressivity and brevity upgrade from javaScala collections api  expressivity and brevity upgrade from java
Scala collections api expressivity and brevity upgrade from java
 
Introduction to programming in scala
Introduction to programming in scalaIntroduction to programming in scala
Introduction to programming in scala
 
Scala collections
Scala collectionsScala collections
Scala collections
 
Programming in Scala - Lecture Four
Programming in Scala - Lecture FourProgramming in Scala - Lecture Four
Programming in Scala - Lecture Four
 

En vedette

Tonka Waters West Girl Scout New Adult Members Training - Fast track v2
Tonka Waters West Girl Scout New Adult Members Training - Fast track v2Tonka Waters West Girl Scout New Adult Members Training - Fast track v2
Tonka Waters West Girl Scout New Adult Members Training - Fast track v2hdurenbe
 
foreveryoungasia
foreveryoungasiaforeveryoungasia
foreveryoungasiaRatha Eagle
 
The Scalactic Way
The Scalactic WayThe Scalactic Way
The Scalactic Waybvenners
 
Sécurisation foncière des exploitations familiales dans les grands périmètres...
Sécurisation foncière des exploitations familiales dans les grands périmètres...Sécurisation foncière des exploitations familiales dans les grands périmètres...
Sécurisation foncière des exploitations familiales dans les grands périmètres...Global Water Initiative - West Africa
 
Lecture du processus de sécurisation foncière en cours par les coopératives r...
Lecture du processus de sécurisation foncière en cours par les coopératives r...Lecture du processus de sécurisation foncière en cours par les coopératives r...
Lecture du processus de sécurisation foncière en cours par les coopératives r...Global Water Initiative - West Africa
 
лекция № 1 кости черепа
лекция № 1 кости черепалекция № 1 кости черепа
лекция № 1 кости черепаlali100226
 
Antena Kaleng (raihan s & syis f)
Antena Kaleng (raihan s & syis f)Antena Kaleng (raihan s & syis f)
Antena Kaleng (raihan s & syis f)raihansayyid
 
Iisrt zz saravana kumar
Iisrt zz saravana kumarIisrt zz saravana kumar
Iisrt zz saravana kumarIISRT
 
Decorative House and Garden Flags
Decorative House and Garden FlagsDecorative House and Garden Flags
Decorative House and Garden Flagsdecorativeflag
 
Sharing is Caring - Web Development Resources
Sharing is Caring - Web Development ResourcesSharing is Caring - Web Development Resources
Sharing is Caring - Web Development ResourcesTrevor Barnes
 

En vedette (14)

Tonka Waters West Girl Scout New Adult Members Training - Fast track v2
Tonka Waters West Girl Scout New Adult Members Training - Fast track v2Tonka Waters West Girl Scout New Adult Members Training - Fast track v2
Tonka Waters West Girl Scout New Adult Members Training - Fast track v2
 
foreveryoungasia
foreveryoungasiaforeveryoungasia
foreveryoungasia
 
The Scalactic Way
The Scalactic WayThe Scalactic Way
The Scalactic Way
 
Synthèse des travaux de groupe
Synthèse des travaux de groupeSynthèse des travaux de groupe
Synthèse des travaux de groupe
 
Sécurisation foncière des exploitations familiales dans les grands périmètres...
Sécurisation foncière des exploitations familiales dans les grands périmètres...Sécurisation foncière des exploitations familiales dans les grands périmètres...
Sécurisation foncière des exploitations familiales dans les grands périmètres...
 
Lecture du processus de sécurisation foncière en cours par les coopératives r...
Lecture du processus de sécurisation foncière en cours par les coopératives r...Lecture du processus de sécurisation foncière en cours par les coopératives r...
Lecture du processus de sécurisation foncière en cours par les coopératives r...
 
лекция № 1 кости черепа
лекция № 1 кости черепалекция № 1 кости черепа
лекция № 1 кости черепа
 
Antena Kaleng (raihan s & syis f)
Antena Kaleng (raihan s & syis f)Antena Kaleng (raihan s & syis f)
Antena Kaleng (raihan s & syis f)
 
Iisrt zz saravana kumar
Iisrt zz saravana kumarIisrt zz saravana kumar
Iisrt zz saravana kumar
 
Cisticercosis
CisticercosisCisticercosis
Cisticercosis
 
Indico Motor
Indico MotorIndico Motor
Indico Motor
 
HALDIA PETROCHEMICALS LIMITED
HALDIA PETROCHEMICALS LIMITEDHALDIA PETROCHEMICALS LIMITED
HALDIA PETROCHEMICALS LIMITED
 
Decorative House and Garden Flags
Decorative House and Garden FlagsDecorative House and Garden Flags
Decorative House and Garden Flags
 
Sharing is Caring - Web Development Resources
Sharing is Caring - Web Development ResourcesSharing is Caring - Web Development Resources
Sharing is Caring - Web Development Resources
 

Similaire à Equality For All!

Functional Programming With Scala
Functional Programming With ScalaFunctional Programming With Scala
Functional Programming With ScalaKnoldus Inc.
 
(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?Tomasz Wrobel
 
Functional programming with Scala
Functional programming with ScalaFunctional programming with Scala
Functional programming with ScalaNeelkanth Sachdeva
 
Programmation fonctionnelle Scala
Programmation fonctionnelle ScalaProgrammation fonctionnelle Scala
Programmation fonctionnelle ScalaSlim Ouertani
 
Power of functions in a typed world
Power of functions in a typed worldPower of functions in a typed world
Power of functions in a typed worldDebasish Ghosh
 
Monadologie
MonadologieMonadologie
Monadologieleague
 
Scala for Java Devs
Scala for Java DevsScala for Java Devs
Scala for Java Devsloverdos
 
Xebicon2013 scala vsjava_final
Xebicon2013 scala vsjava_finalXebicon2013 scala vsjava_final
Xebicon2013 scala vsjava_finalUrs Peter
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with GroovyArturo Herrero
 
Real World Haskell: Lecture 4
Real World Haskell: Lecture 4Real World Haskell: Lecture 4
Real World Haskell: Lecture 4Bryan O'Sullivan
 

Similaire à Equality For All! (20)

Scala ntnu
Scala ntnuScala ntnu
Scala ntnu
 
Functional Programming With Scala
Functional Programming With ScalaFunctional Programming With Scala
Functional Programming With Scala
 
(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?
 
Scala by Luc Duponcheel
Scala by Luc DuponcheelScala by Luc Duponcheel
Scala by Luc Duponcheel
 
Scala introduction
Scala introductionScala introduction
Scala introduction
 
Functional programming with Scala
Functional programming with ScalaFunctional programming with Scala
Functional programming with Scala
 
Coding in Style
Coding in StyleCoding in Style
Coding in Style
 
Programmation fonctionnelle Scala
Programmation fonctionnelle ScalaProgrammation fonctionnelle Scala
Programmation fonctionnelle Scala
 
Power of functions in a typed world
Power of functions in a typed worldPower of functions in a typed world
Power of functions in a typed world
 
Scala intro workshop
Scala intro workshopScala intro workshop
Scala intro workshop
 
Spark workshop
Spark workshopSpark workshop
Spark workshop
 
Monadologie
MonadologieMonadologie
Monadologie
 
Scala for Java Devs
Scala for Java DevsScala for Java Devs
Scala for Java Devs
 
Xebicon2013 scala vsjava_final
Xebicon2013 scala vsjava_finalXebicon2013 scala vsjava_final
Xebicon2013 scala vsjava_final
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with Groovy
 
Real World Haskell: Lecture 4
Real World Haskell: Lecture 4Real World Haskell: Lecture 4
Real World Haskell: Lecture 4
 

Dernier

Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...roncy bisnoi
 
247267395-1-Symmetric-and-distributed-shared-memory-architectures-ppt (1).ppt
247267395-1-Symmetric-and-distributed-shared-memory-architectures-ppt (1).ppt247267395-1-Symmetric-and-distributed-shared-memory-architectures-ppt (1).ppt
247267395-1-Symmetric-and-distributed-shared-memory-architectures-ppt (1).pptssuser5c9d4b1
 
Porous Ceramics seminar and technical writing
Porous Ceramics seminar and technical writingPorous Ceramics seminar and technical writing
Porous Ceramics seminar and technical writingrakeshbaidya232001
 
Introduction and different types of Ethernet.pptx
Introduction and different types of Ethernet.pptxIntroduction and different types of Ethernet.pptx
Introduction and different types of Ethernet.pptxupamatechverse
 
Call Girls in Nagpur Suman Call 7001035870 Meet With Nagpur Escorts
Call Girls in Nagpur Suman Call 7001035870 Meet With Nagpur EscortsCall Girls in Nagpur Suman Call 7001035870 Meet With Nagpur Escorts
Call Girls in Nagpur Suman Call 7001035870 Meet With Nagpur EscortsCall Girls in Nagpur High Profile
 
Top Rated Pune Call Girls Budhwar Peth ⟟ 6297143586 ⟟ Call Me For Genuine Se...
Top Rated  Pune Call Girls Budhwar Peth ⟟ 6297143586 ⟟ Call Me For Genuine Se...Top Rated  Pune Call Girls Budhwar Peth ⟟ 6297143586 ⟟ Call Me For Genuine Se...
Top Rated Pune Call Girls Budhwar Peth ⟟ 6297143586 ⟟ Call Me For Genuine Se...Call Girls in Nagpur High Profile
 
(SHREYA) Chakan Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Esc...
(SHREYA) Chakan Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Esc...(SHREYA) Chakan Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Esc...
(SHREYA) Chakan Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Esc...ranjana rawat
 
Microscopic Analysis of Ceramic Materials.pptx
Microscopic Analysis of Ceramic Materials.pptxMicroscopic Analysis of Ceramic Materials.pptx
Microscopic Analysis of Ceramic Materials.pptxpurnimasatapathy1234
 
Java Programming :Event Handling(Types of Events)
Java Programming :Event Handling(Types of Events)Java Programming :Event Handling(Types of Events)
Java Programming :Event Handling(Types of Events)simmis5
 
(RIA) Call Girls Bhosari ( 7001035870 ) HI-Fi Pune Escorts Service
(RIA) Call Girls Bhosari ( 7001035870 ) HI-Fi Pune Escorts Service(RIA) Call Girls Bhosari ( 7001035870 ) HI-Fi Pune Escorts Service
(RIA) Call Girls Bhosari ( 7001035870 ) HI-Fi Pune Escorts Serviceranjana rawat
 
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur EscortsCall Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur EscortsCall Girls in Nagpur High Profile
 
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete Record
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete RecordCCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete Record
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete RecordAsst.prof M.Gokilavani
 
MANUFACTURING PROCESS-II UNIT-5 NC MACHINE TOOLS
MANUFACTURING PROCESS-II UNIT-5 NC MACHINE TOOLSMANUFACTURING PROCESS-II UNIT-5 NC MACHINE TOOLS
MANUFACTURING PROCESS-II UNIT-5 NC MACHINE TOOLSSIVASHANKAR N
 
Sheet Pile Wall Design and Construction: A Practical Guide for Civil Engineer...
Sheet Pile Wall Design and Construction: A Practical Guide for Civil Engineer...Sheet Pile Wall Design and Construction: A Practical Guide for Civil Engineer...
Sheet Pile Wall Design and Construction: A Practical Guide for Civil Engineer...Dr.Costas Sachpazis
 
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINEMANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINESIVASHANKAR N
 
Coefficient of Thermal Expansion and their Importance.pptx
Coefficient of Thermal Expansion and their Importance.pptxCoefficient of Thermal Expansion and their Importance.pptx
Coefficient of Thermal Expansion and their Importance.pptxAsutosh Ranjan
 
High Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur Escorts
High Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur EscortsHigh Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur Escorts
High Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur EscortsCall Girls in Nagpur High Profile
 
Extrusion Processes and Their Limitations
Extrusion Processes and Their LimitationsExtrusion Processes and Their Limitations
Extrusion Processes and Their Limitations120cr0395
 
result management system report for college project
result management system report for college projectresult management system report for college project
result management system report for college projectTonystark477637
 

Dernier (20)

Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...
 
247267395-1-Symmetric-and-distributed-shared-memory-architectures-ppt (1).ppt
247267395-1-Symmetric-and-distributed-shared-memory-architectures-ppt (1).ppt247267395-1-Symmetric-and-distributed-shared-memory-architectures-ppt (1).ppt
247267395-1-Symmetric-and-distributed-shared-memory-architectures-ppt (1).ppt
 
Porous Ceramics seminar and technical writing
Porous Ceramics seminar and technical writingPorous Ceramics seminar and technical writing
Porous Ceramics seminar and technical writing
 
Introduction and different types of Ethernet.pptx
Introduction and different types of Ethernet.pptxIntroduction and different types of Ethernet.pptx
Introduction and different types of Ethernet.pptx
 
Call Girls in Nagpur Suman Call 7001035870 Meet With Nagpur Escorts
Call Girls in Nagpur Suman Call 7001035870 Meet With Nagpur EscortsCall Girls in Nagpur Suman Call 7001035870 Meet With Nagpur Escorts
Call Girls in Nagpur Suman Call 7001035870 Meet With Nagpur Escorts
 
Top Rated Pune Call Girls Budhwar Peth ⟟ 6297143586 ⟟ Call Me For Genuine Se...
Top Rated  Pune Call Girls Budhwar Peth ⟟ 6297143586 ⟟ Call Me For Genuine Se...Top Rated  Pune Call Girls Budhwar Peth ⟟ 6297143586 ⟟ Call Me For Genuine Se...
Top Rated Pune Call Girls Budhwar Peth ⟟ 6297143586 ⟟ Call Me For Genuine Se...
 
(SHREYA) Chakan Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Esc...
(SHREYA) Chakan Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Esc...(SHREYA) Chakan Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Esc...
(SHREYA) Chakan Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Esc...
 
Microscopic Analysis of Ceramic Materials.pptx
Microscopic Analysis of Ceramic Materials.pptxMicroscopic Analysis of Ceramic Materials.pptx
Microscopic Analysis of Ceramic Materials.pptx
 
Java Programming :Event Handling(Types of Events)
Java Programming :Event Handling(Types of Events)Java Programming :Event Handling(Types of Events)
Java Programming :Event Handling(Types of Events)
 
Roadmap to Membership of RICS - Pathways and Routes
Roadmap to Membership of RICS - Pathways and RoutesRoadmap to Membership of RICS - Pathways and Routes
Roadmap to Membership of RICS - Pathways and Routes
 
(RIA) Call Girls Bhosari ( 7001035870 ) HI-Fi Pune Escorts Service
(RIA) Call Girls Bhosari ( 7001035870 ) HI-Fi Pune Escorts Service(RIA) Call Girls Bhosari ( 7001035870 ) HI-Fi Pune Escorts Service
(RIA) Call Girls Bhosari ( 7001035870 ) HI-Fi Pune Escorts Service
 
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur EscortsCall Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
 
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete Record
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete RecordCCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete Record
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete Record
 
MANUFACTURING PROCESS-II UNIT-5 NC MACHINE TOOLS
MANUFACTURING PROCESS-II UNIT-5 NC MACHINE TOOLSMANUFACTURING PROCESS-II UNIT-5 NC MACHINE TOOLS
MANUFACTURING PROCESS-II UNIT-5 NC MACHINE TOOLS
 
Sheet Pile Wall Design and Construction: A Practical Guide for Civil Engineer...
Sheet Pile Wall Design and Construction: A Practical Guide for Civil Engineer...Sheet Pile Wall Design and Construction: A Practical Guide for Civil Engineer...
Sheet Pile Wall Design and Construction: A Practical Guide for Civil Engineer...
 
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINEMANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
 
Coefficient of Thermal Expansion and their Importance.pptx
Coefficient of Thermal Expansion and their Importance.pptxCoefficient of Thermal Expansion and their Importance.pptx
Coefficient of Thermal Expansion and their Importance.pptx
 
High Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur Escorts
High Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur EscortsHigh Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur Escorts
High Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur Escorts
 
Extrusion Processes and Their Limitations
Extrusion Processes and Their LimitationsExtrusion Processes and Their Limitations
Extrusion Processes and Their Limitations
 
result management system report for college project
result management system report for college projectresult management system report for college project
result management system report for college project
 

Equality For All!

  • 1. Equality For All! Scala by the Bay, 2014 BillVenners Artima, Inc. Escalate Software Saturday, August 9, 2014
  • 2. Equality: An equivalence relation with one element per equivalence class 42 4341 42 = 4241 = 41 43 = 43 reflexive: x = x symmetric: x = y iff y = x transitive: if x = y and y = z then x = z Saturday, August 9, 2014
  • 3. How do I say forty two in code? Let me count the ways... 42 42L 42.0 42.0F 42.toShort '*' 42.toByte BigInt(42) BigDecimal(42) new java.lang.Integer(42) new java.lang.Long(42L) new java.lang.Double(42.0) new java.lang.Float(42.0F) new java.lang.Short(42.toShort) new java.lang.Character(42) new java.lang.Byte(42.toByte) new java.math.BigInteger("42") new java.math.BigDecimal(42) Complex(42.0, 0.0) DigitString("42") DigitString("042") Saturday, August 9, 2014
  • 4. The equals method implements an equivalence relation on non-null object references: • It is reflexive: for any non-null reference value x, x.equals(x) should return true. • It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true. • It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true. • It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified. • For any non-null reference value x, x.equals(null) should return false. Java's equals contract public boolean equals(Object obj) final def == (other:Any): Boolean Saturday, August 9, 2014
  • 5. scala> 42 == 42L res0: Boolean = true scala> BigDecimal(42) == '*' res1: Boolean = true scala> 42.0F == BigInt(42) res2: Boolean = true scala> new java.lang.Float(42.0F) == 42.toShort res3: Boolean = true Co-operative Equality Between Types Saturday, August 9, 2014
  • 6. scala> import scala.collection.mutable import scala.collection.mutable scala> Set(BigInt(4), BigInt(2)) == mutable.Set(4.toByte, 2.toByte) res4: Boolean = true scala> Vector(Left(4), Right(2)) == List(Left(4L), Right(2L)) res5: Boolean = true scala> List(mutable.Set(Map(Some(4L) -> BigInt(2)))) == Vector(Set(mutable.Map(Some(4.0) -> new java.lang.Long(2L)))) res6: Boolean = true Co-operative Equality Between Types Saturday, August 9, 2014
  • 7. scala> Array(4, 2) == Array(4, 2) res7: Boolean = false scala> <forty><two></two></forty> == <forty> <two></two> </forty> res8: Boolean = false scala> new java.math.BigDecimal("42.0") == new java.math.BigDecimal("42.00") res9: Boolean = false scala> 42.0 == 41.9999999999 res10: Boolean = false scala> "case" == "CASE" res11: Boolean = false Wanted: Alternate equalities Saturday, August 9, 2014
  • 8. scala> "forty two" == 42 res19: Boolean = false scala> List(mutable.Set(Map(Some(4L) -> BigInt(2)))) == Vector(Set(mutable.Map(Some("4.0") -> new java.lang.Long(2L)))) res23: Boolean = false Wanted: Type errors But how to decide which comparisons compile? Saturday, August 9, 2014
  • 9. scala> "forty two" == 42 <console>:20: error: types String and Int do not adhere to the type constraint selected for the === and !== operators; the missing implicit parameter is of type org.scalactic.EqualityConstraint[String,Int] "forty two" === 42 ^ scala> BigInt(42) === BigDecimal(42) res1: Boolean = true Fail to compile if L can never equal R. Saturday, August 9, 2014
  • 10. scala> Vector.empty === List.empty <console>:20: error: ambiguous implicit values: both method conflictingEmptySeqConstraint1 in object EqualityConstraint of type [LSEQ[e] <: scala.collection.GenSeq[e], RSEQ[e] <: scala.collection.GenSeq[e]]=> org.scalactic.EqualityConstraint[LSEQ[Nothing],RSEQ[Nothing]] and method conflictingEmptySeqConstraint2 in object EqualityConstraint of type [LSEQ[e] <: scala.collection.GenSeq[e], RSEQ[e] <: scala.collection.GenSeq[e]]=> org.scalactic.EqualityConstraint[LSEQ[Nothing],RSEQ[Nothing]] match expected type org.scalactic.EqualityConstraint[scala.collection.immutable.Vector[A],List[Nothing]] Vector.empty === List.empty ^ scala> Vector.empty === List.empty[Int] res3: Boolean = true scala> Vector.empty[String] === List.empty res4: Boolean = true Fail to compile if L will always equal R. Saturday, August 9, 2014
  • 11. Candidate rule: To compile, an equality comparison must be interesting: values of types L and R can be either equal or unequal. Saturday, August 9, 2014
  • 12. scala> case class Complex(real: Double, imaginary: Double) defined class Complex scala> implicit def convertIntToComplex(i: Int): Complex = Complex(i, 0.0) convertIntToComplex: (i: Int)Complex scala> 42 === Complex(42, 0) <console>:24: error: types Int and Complex do not adhere to the type constraint selected for the === and !== operators; the missing implicit parameter is of type org.scalactic.EqualityConstraint[Int,Complex] 42 === Complex(42, 0) ^ scala> Complex(42, 0) === 42 <console>:24: error: types Complex and Int do not adhere to the type constraint selected for the === and !== operators; the missing implicit parameter is of type org.scalactic.EqualityConstraint[Complex,Int] Complex(42, 0) === 42 ^ What about implicit conversions? Saturday, August 9, 2014
  • 13. scala> implicit val enabler = EqualityEnabledBetween[Int, Complex] enabler: org.scalactic.EqualityEnabledBetween[Int,Complex] = org.scalactic.EqualityEnabledBetween@e5d2d9b scala> 42 === Complex(42, 0) res2: Boolean = true scala> Complex(42, 0) === 42 res3: Boolean = true scala> new AnyShouldWrapper(1) === 1 // Probably shouldn't enable... Intuition: enable some but not all But what would the rule be? Saturday, August 9, 2014
  • 14. OK if the conversion is an injection scala> case class DigitString(digits: String) { | val toInt: Int = digits.toInt | } defined class DigitString scala> implicit def convert(d: DigitString): Int = | d.digits.toInt convertDigitStringToInt: (d: DigitString)Int scala> DigitString("42") === DigitString("042") res0: Boolean = false scala> DigitString("42").toInt === DigitString("042").toInt res1: Boolean = true John C. Reynolds: Using category theory to design implicit conversions and generic operators. Saturday, August 9, 2014
  • 15. How to decide: 1.To compile, an equality comparison must be interesting: values of types L and R can be either equal or unequal. 2.Allow select implicit conversions to be enabled, and recommend that non-widening conversions (non-injections) not be enabled. Saturday, August 9, 2014
  • 16. scala> (Some(1): Option[Int]) === Some(1) res0: Boolean = true scala> Some(1) === (Some(1): Option[Int]) res1: Boolean = true scala> Some(1) === Some(1) res2: Boolean = true What about the implicit conversion from subtype to supertype (<:<)? Saturday, August 9, 2014
  • 17. scala> def eqv[T](a: T, b: T): Boolean = a === b eqv: [T](a: T, b: T)Boolean scala> eqv(1, ()) res3: Boolean = false scala> ((i: Int) => i + 1) === ((i: Int) => i + 1) res4: Boolean = false Even though <:< is an injection, is it always desireable? Saturday, August 9, 2014
  • 19. scala> import EnabledEquality._ import EnabledEquality._ scala> def eqv[T](a: T, b: T): Boolean = a === b <console>:19: error: types T and T do not adhere to the type constraint selected for the === and !== operators; the missing implicit parameter is of type org.scalactic.EqualityConstraint[T,T] def eqv[T](a: T, b: T): Boolean = a === b ^ scala> ((i: Int) => i + 1) === ((i: Int) => i + 1) <console>:20: error: types Int => Int and Int => Int do not adhere to the type constraint selected for the === and !== operators; the missing implicit parameter is of type org.scalactic.EqualityConstraint[Int => Int,Int => Int] ((i: Int) => i + 1) === ((i: Int) => i + 1) ^ EnabledEquality benefit Saturday, August 9, 2014
  • 20. scala> case class Person(name: String) defined class Person scala> Person("Sue") === Person("Sue") <console>:22: error: types Person and Person do not adhere to the type constraint selected for the === and !== operators; the missing implicit parameter is of type org.scalactic.EqualityConstraint[Person,Person] Person("Sue") === Person("Sue") ^ scala> implicit val enabler = new EqualityEnabledFor[Person] enabler: org.scalactic.EqualityEnabledFor[Person] = org.scalactic.EqualityEnabledFor@1289d391 scala> Person("Sue") === Person("Sue") res2: Boolean = true EnabledEquality cost Saturday, August 9, 2014
  • 21. scala> 1 should === ("one") <console>:23: 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.scalactic.Constraint[Int,String] 1 should === ("one") ^ scala> 1 should equal ("one") <console>:23: error: could not find implicit value for parameter typeClass1: org.scalactic.enablers.EvidenceThat[String]#CanEqual[Int] 1 should equal ("one") ^ scala> 1 should be ("one") <console>:23: error: could not find implicit value for parameter typeClass1: org.scalactic.enablers.EvidenceThat[String]#CanEqual[Int] 1 should be ("one") ^ scala> 1 should be_== ("one") org.scalatest.exceptions.TestFailedException: 1 was not equal to "one" ScalaTest's equal, be, and be_== Saturday, August 9, 2014
  • 22. scala> List(1, 2, 3) should contain ("one") <console>:23: error: could not find implicit value for parameter typeClass1: org.scalactic.enablers.EvidenceThat[String]#CanBeContainedIn[List[Int]] List(1, 2, 3) should contain ("one") ^ scala> List(1, 2, 3) should contain oneOf ("one", "two") <console>:23: error: could not find implicit value for parameter evidence: org.scalactic.enablers.EvidenceThat[String]#CanBeContainedIn[List[Int]] List(1, 2, 3) should contain oneOf("one", "two") ^ scala> 1 isIn List(1, 2, 3) res14: Boolean = true scala> "one" isIn List(1, 2, 3) <console>:23: error: Could not find evidence that String can be contained in List[Int]; the missing implicit parameter is of type org.scalactic.enablers.ContainingConstraint[List[Int],String] "one" isIn List(1, 2, 3) ^ ScalaTest's contain, Scalactic's isIn/isNotIn Saturday, August 9, 2014
  • 23. if sufficientTimeRemains then (Q => A) else thanks artima.com/shop 15% discount coupon code: BYTHEBAY2014 Saturday, August 9, 2014
  • 24. scala> 1L === 1 res0: Boolean = true scala> 1 === 1L <console>:14: error: could not find implicit value for parameter F0: scalaz.Equal[Any] 1 === 1L ^ Scalaz or Spire Scalactic scala> 1L === 1 res7: Boolean = true scala> 1 === 1L res8: Boolean = true Equal[T], Eq[T] EqualityConstraint[L, R] Equivalence[T] Saturday, August 9, 2014