I am unclear how to achieve path dependent types in the following snippet. The intention is to be able to use the "meld" method to merge two Heaps. That AFAIK requires path dependent types.
Here is the trait
trait Heap {
type H // type of a heap
type A // type of an element
def ord: Ordering[Heap#A] // ordering on elements
def meld(h1: Heap#H, h2: Heap#H): Heap#H // the heap resulting from merging h1 and h2
..
}
Here is part of the implementation
class HeapImpl extends Heap {
override type H = HeapImpl // this.type
override type A = Integer
..
// the heap resulting from inserting x into h
override def meld(h1: Heap#H, h2: Heap#H): Heap#H = {
while (!isEmpty(h2)) {
insert(deleteMin(h2),h1)
}
this
}
The return value "this" on the meld method suffers the compilation error:
Expression HeapImpl does not conform to expected type Heap#H
trait Heap {
type H <: Heap // type of a heap (added requirement that it must be a heap)
type A // type of an element
def ord: Ordering[A] // ordering on elements
def meld(h1: H, h2: H): H // the heap resulting from merging h1 and h2
..
}
Now, when you define
override def meld(h1: H, h2: H): H
in HeapImpl
, H
is just HeapImpl
and the return type will conform.
This way, A
and H
in the methods are the same as defined in your type ...
. Path-dependent types mean that you can write types like heap.A
(where heap
is a Heap
).
I'll also note that your implementation of meld
looks strange. It looks like you are inserting elements of h2
into h1
(if not, what does the second argument to insert
mean?), but then instead of returning h1
you return this
.