This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Why doesn't the compiler find this mistake...?

9 replies
Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.

Hi,

let's say i have a method

class SplayTree[ T ]()( implicit view : (T) => Ordered[ T ])
extends scala.collection.mutable.Set[ T ] {

...

def findMax: Option[ T ] = {
if( root == null ) return None
var x = root
while( x.right != null ) x = x.right
splay( x.elem )
Some( x.elem )
}

...
}

and i am testing:

val min = t.findMin
if( min != 2 ) {
println( "findMin error! Should be 2 but is " + min )
}

why doesn't the compiler tell me that i'm having a type mismatch ( if
( min != 2 ) compares an Option[ Int ] with an Int )? instead the
test fails with printout:

"findMin error! Should be 2 but is Some(2)"

... how can i avoid this problem?

thanks, -sciss-

Jorge Ortiz
Joined: 2008-12-16,
User offline. Last seen 29 weeks 4 days ago.
Re: Why doesn't the compiler find this mistake...?
Because Scala inherits == (and !=) from Java's "equals" method, which takes an Any as its argument.

How do you prevent this mistake? Try findbugs http://findbugs.sourceforge.net/

--j

On Wed, May 6, 2009 at 2:50 PM, Sciss <contact@sciss.de> wrote:
Hi,

let's say i have a method

class SplayTree[ T ]()( implicit view : (T) => Ordered[ T ])
extends scala.collection.mutable.Set[ T ] {
       
       ...

   def findMax: Option[ T ] = {
       if( root == null ) return None
       var x = root
       while( x.right != null ) x = x.right
       splay( x.elem )
       Some( x.elem )
   }

       ...
}

and i am testing:

      val min = t.findMin
       if( min != 2 ) {
           println( "findMin error! Should be 2 but is " + min )
       }

why doesn't the compiler tell me that i'm having a type mismatch ( if( min != 2 ) compares an Option[ Int ] with an Int )? instead the test fails with printout:

"findMin error! Should be 2 but is Some(2)"

... how can i avoid this problem?

thanks, -sciss-



Andrew O'Malley
Joined: 2009-03-19,
User offline. Last seen 42 years 45 weeks ago.
Re: Why doesn't the compiler find this mistake...?
You might be interested in scalaz's Equal functionality: http://code.google.com/p/scalaz/source/browse/trunk/src/main/scala/scalaz/Equal.scala
This defines an Equal trait that restricts the comparison to objects of the same type. Via implicits you can then compare objects using the "===" operator and will get the compiler errors you are after.
On 07/05/2009, at 9:55 AM, Jorge Ortiz wrote:
Because Scala inherits == (and !=) from Java's "equals" method, which takes an Any as its argument.

How do you prevent this mistake? Try findbugs http://findbugs.sourceforge.net/

--j

On Wed, May 6, 2009 at 2:50 PM, Sciss <contact@sciss.de> wrote:
Hi,

let's say i have a method

class SplayTree[ T ]()( implicit view : (T) => Ordered[ T ])
extends scala.collection.mutable.Set[ T ] {
       
       ...

   def findMax: Option[ T ] = {
       if( root == null ) return None
       var x = root
       while( x.right != null ) x = x.right
       splay( x.elem )
       Some( x.elem )
   }

       ...
}

and i am testing:

      val min = t.findMin
       if( min != 2 ) {
           println( "findMin error! Should be 2 but is " + min )
       }

why doesn't the compiler tell me that i'm having a type mismatch ( if( min != 2 ) compares an Option[ Int ] with an Int )? instead the test fails with printout:

"findMin error! Should be 2 but is Some(2)"

... how can i avoid this problem?

thanks, -sciss-




Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.
Re: Why doesn't the compiler find this mistake...?

ah very nice, thank you!

Am 07.05.2009 um 02:22 schrieb Andrew O'Malley:

> You might be interested in scalaz's Equal functionality: http://
> code.google.com/p/scalaz/source/browse/trunk/src/main/scala/scalaz/
> Equal.scala
>
> This defines an Equal trait that restricts the comparison to
> objects of the same type. Via implicits you can then compare
> objects using the "===" operator and will get the compiler errors
> you are after.
>
> On 07/05/2009, at 9:55 AM, Jorge Ortiz wrote:
>
>> Because Scala inherits == (and !=) from Java's "equals" method,
>> which takes an Any as its argument.
>>
>> How do you prevent this mistake? Try findbugs http://
>> findbugs.sourceforge.net/
>>
>> --j
>>
>> On Wed, May 6, 2009 at 2:50 PM, Sciss wrote:
>> Hi,
>>
>> let's say i have a method
>>
>> class SplayTree[ T ]()( implicit view : (T) => Ordered[ T ])
>> extends scala.collection.mutable.Set[ T ] {
>>
>> ...
>>
>> def findMax: Option[ T ] = {
>> if( root == null ) return None
>> var x = root
>> while( x.right != null ) x = x.right
>> splay( x.elem )
>> Some( x.elem )
>> }
>>
>> ...
>> }
>>
>> and i am testing:
>>
>> val min = t.findMin
>> if( min != 2 ) {
>> println( "findMin error! Should be 2 but is " + min )
>> }
>>
>> why doesn't the compiler tell me that i'm having a type mismatch
>> ( if( min != 2 ) compares an Option[ Int ] with an Int )? instead
>> the test fails with printout:
>>
>> "findMin error! Should be 2 but is Some(2)"
>>
>> ... how can i avoid this problem?
>>
>> thanks, -sciss-
>>
>>
>>
>

Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.
Re: Why doesn't the compiler find this mistake...?

thank you for the findbugs link!

Am 07.05.2009 um 01:55 schrieb Jorge Ortiz:

> Because Scala inherits == (and !=) from Java's "equals" method,
> which takes an Any as its argument.
>
> How do you prevent this mistake? Try findbugs http://
> findbugs.sourceforge.net/
>
> --j
>
> On Wed, May 6, 2009 at 2:50 PM, Sciss wrote:
> Hi,
>
> let's say i have a method
>
> class SplayTree[ T ]()( implicit view : (T) => Ordered[ T ])
> extends scala.collection.mutable.Set[ T ] {
>
> ...
>
> def findMax: Option[ T ] = {
> if( root == null ) return None
> var x = root
> while( x.right != null ) x = x.right
> splay( x.elem )
> Some( x.elem )
> }
>
> ...
> }
>
> and i am testing:
>
> val min = t.findMin
> if( min != 2 ) {
> println( "findMin error! Should be 2 but is " + min )
> }
>
> why doesn't the compiler tell me that i'm having a type mismatch
> ( if( min != 2 ) compares an Option[ Int ] with an Int )? instead
> the test fails with printout:
>
> "findMin error! Should be 2 but is Some(2)"
>
> ... how can i avoid this problem?
>
> thanks, -sciss-
>
>
>

Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.
Re: Why doesn't the compiler find this mistake...?

stumpled again over the same problem.

but this

def ident[T]( a: T, b: T ) : Boolean = {
println( "Comparing a = " + a + "; with b = " + b )
a.equals( b )
}

does not inforce a and b be of the same type... i don't understand why?

like i have

val a: TypeA
val b: TypeB = TypeB.wrap( a )
implicit def bToA( x: TypeB ) : TypeA = { ... unwrap TypeA which is
stored in TypeB ... }

ident( a, b )
// --> false !!

although bToA( b ) results in a.

i'm confused....

ciao, -sciss-

Am 07.05.2009 um 02:22 schrieb Andrew O'Malley:

> You might be interested in scalaz's Equal functionality: http://
> code.google.com/p/scalaz/source/browse/trunk/src/main/scala/scalaz/
> Equal.scala
>
> This defines an Equal trait that restricts the comparison to
> objects of the same type. Via implicits you can then compare
> objects using the "===" operator and will get the compiler errors
> you are after.
>
> On 07/05/2009, at 9:55 AM, Jorge Ortiz wrote:
>
>> Because Scala inherits == (and !=) from Java's "equals" method,
>> which takes an Any as its argument.
>>
>> How do you prevent this mistake? Try findbugs http://
>> findbugs.sourceforge.net/
>>
>> --j
>>
>> On Wed, May 6, 2009 at 2:50 PM, Sciss wrote:
>> Hi,
>>
>> let's say i have a method
>>
>> class SplayTree[ T ]()( implicit view : (T) => Ordered[ T ])
>> extends scala.collection.mutable.Set[ T ] {
>>
>> ...
>>
>> def findMax: Option[ T ] = {
>> if( root == null ) return None
>> var x = root
>> while( x.right != null ) x = x.right
>> splay( x.elem )
>> Some( x.elem )
>> }
>>
>> ...
>> }
>>
>> and i am testing:
>>
>> val min = t.findMin
>> if( min != 2 ) {
>> println( "findMin error! Should be 2 but is " + min )
>> }
>>
>> why doesn't the compiler tell me that i'm having a type mismatch
>> ( if( min != 2 ) compares an Option[ Int ] with an Int )? instead
>> the test fails with printout:
>>
>> "findMin error! Should be 2 but is Some(2)"
>>
>> ... how can i avoid this problem?
>>
>> thanks, -sciss-
>>
>>
>>
>

Ricky Clarkson
Joined: 2008-12-19,
User offline. Last seen 3 years 2 weeks ago.
Re: Why doesn't the compiler find this mistake...?

The issue is that Scala supports this broken feature from OOP called
'subtyping'. There is a type T that both a and b extend, even if it's
as unspecific as Any.

OOP, helping people be vague since, um..

def ident[T](a: T)(b: T): Boolean ... should do it, because Scala's
type parameter inference only looks at the first parameter list.

2009/6/9 Sciss :
> stumpled again over the same problem.
>
> but this
>
>        def ident[T]( a: T, b: T ) : Boolean = {
>                println( "Comparing a = " + a + "; with b = " + b )
>                a.equals( b )
>        }
>
> does not inforce a and b be of the same type... i don't understand why?
>
> like i have
>
>        val a: TypeA
>        val b: TypeB = TypeB.wrap( a )
>        implicit def bToA( x: TypeB ) : TypeA = { ... unwrap TypeA which is
> stored in TypeB ... }
>
>        ident( a, b )
>        // --> false !!
>
> although bToA( b ) results in a.
>
> i'm confused....
>
> ciao, -sciss-
>
>
>
> Am 07.05.2009 um 02:22 schrieb Andrew O'Malley:
>
>> You might be interested in scalaz's Equal functionality:
>> http://code.google.com/p/scalaz/source/browse/trunk/src/main/scala/scala...
>>
>> This defines an Equal trait that restricts the comparison to objects of
>> the same type. Via implicits you can then compare objects using the "==="
>> operator and will get the compiler errors you are after.
>>
>> On 07/05/2009, at 9:55 AM, Jorge Ortiz wrote:
>>
>>> Because Scala inherits == (and !=) from Java's "equals" method, which
>>> takes an Any as its argument.
>>>
>>> How do you prevent this mistake? Try findbugs
>>> http://findbugs.sourceforge.net/
>>>
>>> --j
>>>
>>> On Wed, May 6, 2009 at 2:50 PM, Sciss wrote:
>>> Hi,
>>>
>>> let's say i have a method
>>>
>>> class SplayTree[ T ]()( implicit view : (T) => Ordered[ T ])
>>> extends scala.collection.mutable.Set[ T ] {
>>>
>>>       ...
>>>
>>>   def findMax: Option[ T ] = {
>>>       if( root == null ) return None
>>>       var x = root
>>>       while( x.right != null ) x = x.right
>>>       splay( x.elem )
>>>       Some( x.elem )
>>>   }
>>>
>>>       ...
>>> }
>>>
>>> and i am testing:
>>>
>>>      val min = t.findMin
>>>       if( min != 2 ) {
>>>           println( "findMin error! Should be 2 but is " + min )
>>>       }
>>>
>>> why doesn't the compiler tell me that i'm having a type mismatch ( if(
>>> min != 2 ) compares an Option[ Int ] with an Int )? instead the test fails
>>> with printout:
>>>
>>> "findMin error! Should be 2 but is Some(2)"
>>>
>>> ... how can i avoid this problem?
>>>
>>> thanks, -sciss-
>>>
>>>
>>>
>>
>
>

Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.
Re: Why doesn't the compiler find this mistake...?

ah ok, thanks for the explanation + the trick to do it!

ciao, -sciss-

Am 09.06.2009 um 12:41 schrieb Ricky Clarkson:

> The issue is that Scala supports this broken feature from OOP called
> 'subtyping'. There is a type T that both a and b extend, even if it's
> as unspecific as Any.
>
> OOP, helping people be vague since, um..
>
> def ident[T](a: T)(b: T): Boolean ... should do it, because Scala's
> type parameter inference only looks at the first parameter list.
>
> 2009/6/9 Sciss :
>> stumpled again over the same problem.
>>
>> but this
>>
>> def ident[T]( a: T, b: T ) : Boolean = {
>> println( "Comparing a = " + a + "; with b = " + b )
>> a.equals( b )
>> }
>>
>> does not inforce a and b be of the same type... i don't understand
>> why?
>>
>> like i have
>>
>> val a: TypeA
>> val b: TypeB = TypeB.wrap( a )
>> implicit def bToA( x: TypeB ) : TypeA = { ... unwrap TypeA
>> which is
>> stored in TypeB ... }
>>
>> ident( a, b )
>> // --> false !!
>>
>> although bToA( b ) results in a.
>>
>> i'm confused....
>>
>> ciao, -sciss-
>>
>>
>>
>> Am 07.05.2009 um 02:22 schrieb Andrew O'Malley:
>>
>>> You might be interested in scalaz's Equal functionality:
>>> http://code.google.com/p/scalaz/source/browse/trunk/src/main/
>>> scala/scalaz/Equal.scala
>>>
>>> This defines an Equal trait that restricts the comparison to
>>> objects of
>>> the same type. Via implicits you can then compare objects using
>>> the "==="
>>> operator and will get the compiler errors you are after.
>>>
>>> On 07/05/2009, at 9:55 AM, Jorge Ortiz wrote:
>>>
>>>> Because Scala inherits == (and !=) from Java's "equals" method,
>>>> which
>>>> takes an Any as its argument.
>>>>
>>>> How do you prevent this mistake? Try findbugs
>>>> http://findbugs.sourceforge.net/
>>>>
>>>> --j
>>>>
>>>> On Wed, May 6, 2009 at 2:50 PM, Sciss wrote:
>>>> Hi,
>>>>
>>>> let's say i have a method
>>>>
>>>> class SplayTree[ T ]()( implicit view : (T) => Ordered[ T ])
>>>> extends scala.collection.mutable.Set[ T ] {
>>>>
>>>> ...
>>>>
>>>> def findMax: Option[ T ] = {
>>>> if( root == null ) return None
>>>> var x = root
>>>> while( x.right != null ) x = x.right
>>>> splay( x.elem )
>>>> Some( x.elem )
>>>> }
>>>>
>>>> ...
>>>> }
>>>>
>>>> and i am testing:
>>>>
>>>> val min = t.findMin
>>>> if( min != 2 ) {
>>>> println( "findMin error! Should be 2 but is " + min )
>>>> }
>>>>
>>>> why doesn't the compiler tell me that i'm having a type mismatch
>>>> ( if(
>>>> min != 2 ) compares an Option[ Int ] with an Int )? instead the
>>>> test fails
>>>> with printout:
>>>>
>>>> "findMin error! Should be 2 but is Some(2)"
>>>>
>>>> ... how can i avoid this problem?
>>>>
>>>> thanks, -sciss-
>>>>
>>>>
>>>>
>>>
>>
>>

Florian Hars
Joined: 2008-12-18,
User offline. Last seen 42 years 45 weeks ago.
Re: Why doesn't the compiler find this mistake...?

Ricky Clarkson schrieb:
> OOP, helping people be vague since, um..

1967. http://en.wikipedia.org/wiki/Simula

> def ident[T](a: T)(b: T): Boolean ... should do it, because Scala's
> type parameter inference only looks at the first parameter list.

Or tell it about the types you want. With these definitions:

case class TypeA(foo: Int)
case class TypeB(a: TypeA)
implicit def bToA(b: TypeB) = b.a

val a = TypeA(42)
val b= TypeB(a)

you get:

scala> ident(a, b)
Comparing a = TypeA(42); with b = TypeB(TypeA(42))
res0: Boolean = false

scala> ident[TypeA](a, b)
Comparing a = TypeA(42); with b = TypeA(42)
res1: Boolean = true

Your trick breaks reflexivity:

scala> ident(a)(b)
Comparing a = TypeA(42); with b = TypeA(42)
res2: Boolean = true

scala> ident(b)(a)
:13: error: type mismatch;
found : TypeA
required: TypeB
ident(b)(a)
^
- Florian.

Ricky Clarkson
Joined: 2008-12-19,
User offline. Last seen 3 years 2 weeks ago.
Re: Why doesn't the compiler find this mistake...?

I was not aware that reflexivity was a requirement.

2009/6/9 Florian Hars :
> Ricky Clarkson schrieb:
>> OOP, helping people be vague since, um..
>
> 1967. http://en.wikipedia.org/wiki/Simula
>
>> def ident[T](a: T)(b: T): Boolean ... should do it, because Scala's
>> type parameter inference only looks at the first parameter list.
>
> Or tell it about the types you want. With these definitions:
>
> case class TypeA(foo: Int)
> case class TypeB(a: TypeA)
> implicit def bToA(b: TypeB) = b.a
>
> val a = TypeA(42)
> val b= TypeB(a)
>
> you get:
>
> scala> ident(a, b)
> Comparing a = TypeA(42); with b = TypeB(TypeA(42))
> res0: Boolean = false
>
> scala> ident[TypeA](a, b)
> Comparing a = TypeA(42); with b = TypeA(42)
> res1: Boolean = true
>
> Your trick breaks reflexivity:
>
> scala> ident(a)(b)
> Comparing a = TypeA(42); with b = TypeA(42)
> res2: Boolean = true
>
> scala> ident(b)(a)
> :13: error: type mismatch;
>  found   : TypeA
>  required: TypeB
>       ident(b)(a)
>                ^
> - Florian.
>

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland