Note that there are some explanatory texts on larger screens.

plurals
  1. POWhy doesn't this code compile? Is this really unsafe?
    primarykey
    data
    text
    <p>Consider this simple binary tree type:</p> <pre><code>abstract class BinaryTree[T] { type Repr &lt;: BinaryTree[T] def left: Repr def value: T def right: Repr def height: Int def add(elem: T): Repr = if ( left.height &lt;= right.height ) copy( left.add( elem ), right) else copy( left, right.add(elem)) def copy( left: Repr, right: Repr ) : Repr } abstract class BinarySearchTree[T] extends BinaryTree[T] { type Repr &lt;: BinarySearchTree[T] def ordering: Ordering[T] override def add(elem: T) = if ( ordering.equiv( elem, value ) ) this.asInstanceOf[Repr] else if ( ordering.lt(elem, value) ) copy( left.add( elem ), right ) else copy( left, right.add( elem ) ) } class ScapegoatTree[T]( val value: T, val left: ScapegoatTree[T], val right: ScapegoatTree[T] )(implicit val ordering: Ordering[T]) extends BinarySearchTree[T] { type Repr = ScapegoatTree[T] def add = this /* snip */ def copy( left: ScapegoatTree[T], right: ScapegoatTree[T] ) = new ScapegoatTree( value, left, right ) } class BalancedBinaryTree[T]( val value: T, val left: BalancedBinaryTree[T], val right: BalancedBinaryTree[T] )(implicit val ordering: Ordering[T]) extends BinarySearchTree[T] { type Repr = BalancedBinaryTree[T] def add = this /* snip */ def copy( left: BalancedBinaryTree[T], right: BalancedBinaryTree[T] ) = new BalancedBinaryTree( value, left, right ) } </code></pre> <p>Using Scala 2.9 in Scala-IDE, the add method fails to compile because copy takes a <code>Repr</code> while <code>left.add(elem)</code> and <code>right.add(elem)</code> return a <code>Repr#Repr</code>. As far as I can tell, <code>Repr#Repr</code> must always be a subtype of <code>Repr</code>, and therefore it should be safe. Have I failed to consider some case, or is this one of those fortunately rare instances where the type system prevents you from doing something that ought to work?</p> <p>Also, is there any way I could change my type definition so this would be legal, or assert to the compiler that <code>Repr#Repr</code> must be a subtype of <code>Repr</code> (aside from a cast, I mean). I'm still getting used to Scala and I'm not sure I've fully comprehended the type system yet. I did get it to compile by writing an implicit method that does a cast, but that feels like more of a workaround than a solution.</p> <p>Thanks in advance for your help.</p> <p>Edit: I should add that in my actual implementation of this I have subclasses that further restrict the type of Repr, if that makes a difference.</p> <p>Edit 2: Added more code, as requested. This issue appears in the <code>BinarySearchTree</code> type as well, but not in concrete implementations such as <code>ScapegoatTree</code> where <code>Repr</code> is specified. There is also a concrete implementation of the basic <code>BinaryTree</code>, but I'm trying to keep it minimal so you don't have to wade through too much unnecessary code.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload