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

Accessing and referencing Nested Classes: Type Mistmatch Error problem

7 replies
shanemagrath@gm...
Joined: 2011-07-16,
User offline. Last seen 42 years 45 weeks ago.

I have created an abstract Class called Graph with two nested Case
Classes, partially described as follows

abstract class Graph[N,E]{
//Graph Nodes
case class Node(value:N){

}
//Graph Edges
case class Edge(s:Node,t:Node,value:E){

}
//NODE METHODS
/** Add a Node to the graph iff the value doesn't exist. If it
does, simply return the existing Node for that value */
def add(sv:N):Node = {…}
/** True iff the two nodes are neighbours of each other. That is,
if there exists an edge connecting
* either s --> t or t --> s. */
def areNeighbours(s:Node,t:Node):Boolean = {(areAdjacent(s,t) ||
(areAdjacent(t,s)))}
/** True iff two nodes are adjacent to each other - that is,
there exists an Edge from s --> t.
* Note: this can be different from being neighbours in the case
of a DirectedGraph. */
def areAdjacent(s:Node,t:Node):Boolean = { (neighbours(s) contains
t) }

}

I create a concrete class as follows:

/** Model of a Simple Graph.
* Note: A Simple graph is a graph with undirected edges. */
class SimpleGraph[N,E] extends Graph[N,E]{

}

Elsewhere in my ScalaTest / Junit tests, I make the declarations

var G1 = new SimpleGraph[String,String]()
var G2 = new SimpleGraph[String,String]()
//Nodes
var n1_1:SimpleGraph[String,String]#Node = _
var n1_2:SimpleGraph[String,String]#Node = _

initialized as

@Before def initialise(){
n1_1 = G1 add "A"
n1_2 = G1 add "B"
n1_3 = G1 add "C"

} //

I then try to make the following test:

@Test def Node_Neighbours_1(){
//confirms that nodes which are neighbours are confirmed as
such
(G1.areNeighbours(n1_1, n1_2)) should be (true)
}

I get the following Type Mismatch error:

type mismatch; found : graph.SimpleGraph[String,String]#Node
required: _113.Node where val _113: graph.SimpleGraph[String,String]

Note my Node declaration:
Var n1_1:SimpleGraph[String,String]#Node = _

I wanted to keep the Node case class internal to Graph because of the
parameterised types which are shared between Graph, Node and Edge. But
I can’t see how to deal with this type mismatch problem…

Any help much appreciated.

Shane

Lars Hupel
Joined: 2010-06-23,
User offline. Last seen 44 weeks 3 days ago.
Re: Accessing and referencing Nested Classes: Type Mistmatch Err

> Elsewhere in my ScalaTest / Junit tests, I make the declarations
>
> var G1 = new SimpleGraph[String,String]()
> var G2 = new SimpleGraph[String,String]()
> //Nodes
> var n1_1:SimpleGraph[String,String]#Node = _
> var n1_2:SimpleGraph[String,String]#Node = _
>
> initialized as
>
> @Before def initialise(){
> n1_1 = G1 add "A"
> n1_2 = G1 add "B"
> n1_3 = G1 add "C"
> …
> } //

First of all, that is very bad style. Try to keep everything as 'val's,
and avoid 'null' values.

> I get the following Type Mismatch error:
>
> type mismatch; found : graph.SimpleGraph[String,String]#Node
> required: _113.Node where val _113: graph.SimpleGraph[String,String]

That's a path-dependent type. Because Node is an inner class of the
Graph class, its instances are bound to a parent instance (or path) of
Graph. You have to declare 'n1_1' with the type 'G1.Node'. (IIRC this
only works if 'G1' is a stable identifier, i. e. a 'val'.)

shanemagrath@gm...
Joined: 2011-07-16,
User offline. Last seen 42 years 45 weeks ago.
Re: Accessing and referencing Nested Classes: Type Mistmatch Err

Thanks Lars,

1) Understand about the bad style. However, this is in a ScalaTest
class and I'm reusing the variables in every test. Setting them to
"val" would prevent the test reuse.

2) Are you saying that when I define n1_1 as
var n1_1:SimpleGraph[String,String]#Node = _

where the type is "SimpleGraph[String,String]#Node" that this isn't
enough (noting the #Node suffix)?

Interestingly, the following test compiles and passes just fine:

@Test def Node_Equality_1(){
// Nodes with the same values are equal
(n1_1 == n2_1) should be (true)
(n1_2 == n2_2) should be (true)
(n1_3 == n2_3) should be (true)
}

Thanks for your thinking...

Shane
On Jul 16, 5:07 pm, Lars Hupel wrote:
> > Elsewhere in my ScalaTest / Junit tests, I make the declarations
>
> >     var  G1 = new SimpleGraph[String,String]()
> >     var  G2 = new SimpleGraph[String,String]()
> >     //Nodes
> >     var  n1_1:SimpleGraph[String,String]#Node = _
> >     var  n1_2:SimpleGraph[String,String]#Node = _
>
> > initialized as
>
> > @Before def initialise(){
> >          n1_1 = G1 add "A"
> >          n1_2 = G1 add "B"
> >          n1_3 = G1 add "C"
> >          
> > }        //
>
> First of all, that is very bad style. Try to keep everything as 'val's,
> and avoid 'null' values.
>
> > I get the following Type Mismatch error:
>
> > type mismatch;  found   : graph.SimpleGraph[String,String]#Node
> > required: _113.Node where val _113: graph.SimpleGraph[String,String]
>
> That's a path-dependent type. Because Node is an inner class of the
> Graph class, its instances are bound to a parent instance (or path) of
> Graph. You have to declare 'n1_1' with the type 'G1.Node'. (IIRC this
> only works if 'G1' is a stable identifier, i. e. a 'val'.)

Tony Morris 2
Joined: 2009-03-20,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: Accessing and referencing Nested Classes: Type Mistmatc

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 16/07/11 20:53, smagrath wrote:
> Thanks Lars,
>
> 1) Understand about the bad style. However, this is in a ScalaTest
> class and I'm reusing the variables in every test. Setting them to
> "val" would prevent the test reuse.

The contrary is true. Not setting to val prevents reuse.

Although it won't help your type error, the issue of "Accessing and
referencing Nested Classes" was discussed recently on another thread
regarding lenses.

Lars Hupel
Joined: 2010-06-23,
User offline. Last seen 44 weeks 3 days ago.
Re: Accessing and referencing Nested Classes: Type Mistmatch Err

> The contrary is true. Not setting to val prevents reuse.

I'd like to second that.

> 1) Understand about the bad style. However, this is in a ScalaTest
> class and I'm reusing the variables in every test. Setting them to
> "val" would prevent the test reuse.

Maybe you could put them into an inner class of your test class and
re-instantiate them every time. Or, even better, think about making your
Graph class immutable.

Back to your issue.

> 2) Are you saying that when I define n1_1 as
> var n1_1:SimpleGraph[String,String]#Node = _
>
> where the type is "SimpleGraph[String,String]#Node" that this isn't
> enough (noting the #Node suffix)?

'#' stands for a type projection. That is, it is a super type of every
't1.Node' where 't1' is an instance of 'SimpleGraph', but not vice-versa
(otherwise, they would be equal).

I strongly recommend that you read a bit about path-dependent types and
projections, e. g. in .

> Interestingly, the following test compiles and passes just fine:
>
> @Test def Node_Equality_1(){
> // Nodes with the same values are equal
> (n1_1 == n2_1) should be (true)
> (n1_2 == n2_2) should be (true)
> (n1_3 == n2_3) should be (true)
> }

That's because of two reasons:

* '==' (or 'equals') is not type safe, so the compiler doesn't complain
* default 'equals' for case classes doesn't check the parent reference
(not sure about this one)

shanemagrath@gm...
Joined: 2011-07-16,
User offline. Last seen 42 years 45 weeks ago.
Re: Accessing and referencing Nested Classes: Type Mistmatch Err

Thanks for the heads up - I'll give it a go tomorrow.

Shane

On Jul 16, 9:06 pm, Lars Hupel wrote:
> > The contrary is true. Not setting to val prevents reuse.
>
> I'd like to second that.
>
> > 1) Understand about the bad style. However, this is in a ScalaTest
> > class and I'm reusing the variables in every test. Setting them to
> > "val" would prevent the test reuse.
>
> Maybe you could put them into an inner class of your test class and
> re-instantiate them every time. Or, even better, think about making your
> Graph class immutable.
>
> Back to your issue.
>
> > 2) Are you saying that when I define n1_1 as
> > var  n1_1:SimpleGraph[String,String]#Node = _
>
> > where the type is "SimpleGraph[String,String]#Node" that this isn't
> > enough (noting the #Node suffix)?
>
> '#' stands for a type projection. That is, it is a super type of every
> 't1.Node' where 't1' is an instance of 'SimpleGraph', but not vice-versa
> (otherwise, they would be equal).
>
> I strongly recommend that you read a bit about path-dependent types and
> projections, e. g. in .
>
> > Interestingly, the following test compiles and passes just fine:
>
> > @Test def Node_Equality_1(){
> >         // Nodes with the same values are equal
> >         (n1_1 == n2_1) should be (true)
> >         (n1_2 == n2_2) should be (true)
> >         (n1_3 == n2_3) should be (true)
> >     }
>
> That's because of two reasons:
>
> * '==' (or 'equals') is not type safe, so the compiler doesn't complain
> * default 'equals' for case classes doesn't check the parent reference
> (not sure about this one)

Florian Hars 3
Joined: 2011-05-08,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: Accessing and referencing Nested Classes: Type Mistmatc

On Sat, Jul 16, 2011 at 03:53:58AM -0700, smagrath wrote:
> where the type is "SimpleGraph[String,String]#Node" that this isn't
> enough (noting the #Node suffix)?

This is not only not enough, this is exactly the bug in your code
the compiler is complaining about. That is the type of a Node in
*any* SimpleGraph[String,String], but the methods of graph G1
are only defined on nodes of graph G1. That is what Lars wrote,
the type of n1_1 must be G1.Node.

> Interestingly, the following test compiles and passes just fine:
>
> @Test def Node_Equality_1(){
> // Nodes with the same values are equal
> (n1_1 == n2_1) should be (true)

Yeah, most popular languages are fundamentally broken wrt. equality, which
is why scala has == and eq and a whole chapter on how to define equals in
in the staircase book (that still didn't prevent the problems discussed in
the recent thread on Proxy and case classes), Common Lisp has =, string=, eq,
eql, equal and equalp, PHP has == and === and so on.
Live with it or use haskell.

- Florian.

dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: Re: Accessing and referencing Nested Classes: Type Mistmatc

On Sat, Jul 16, 2011 at 08:27, Florian Hars wrote:
>
> Yeah, most popular languages are fundamentally broken wrt. equality, which
> is why scala has == and eq and a whole chapter on how to define equals in
> in the staircase book (that still didn't prevent the problems discussed in
> the recent thread on Proxy and case classes), Common Lisp has =, string=, eq,
> eql, equal and equalp, PHP has == and === and so on.
> Live with it or use haskell.

Mind you, Proxy is broken by design, even if it is true that it got
_more_ broken.

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