Package: ghc6
Version: 6.4-4

  I was experimenting with writing a functional heap when I got the following 
error from ghc:


ghc-6.4: panic! (the `impossible' happened, GHC version 6.4):
        ds_app_type PriorityQueue.PriorityQueue{tc r1qv} [k{tv a1vx}]

  This seems to be tracable to a confusion of thought on my part about what I 
was doing with a typeclass declaration, but I believe it's also a bug in ghc.  
I've attached the file I was trying to compile; please don't laugh too hard 
at the silly Haskell mistake I made ;-).

  Daniel

-- 
/------------------- Daniel Burrows <[EMAIL PROTECTED]> ------------------\
|     You are standing west of a white house.  There is a mailbox here.     |
\- Does your computer have Super Cow Powers? ------- http://www.debian.org -/
module PriorityQueue(
                     Heap,
                     PriorityQueue(..)
                    ) where

import qualified Data.Set as Set

-- Implements Ye Olde Priority Queue.  You probably want to import
-- this qualified.



-- A priority queue lets you create a set of objects and extract
-- the minimum element at any time.
class (Ord k) => PriorityQueue k where
    empty :: PriorityQueue k
    null :: PriorityQueue k -> Bool
    insert :: k -> PriorityQueue k -> PriorityQueue k
    -- Return the least queue element:
    getMin :: PriorityQueue k -> k
    -- Remove and discard the least queue element:
    pop :: PriorityQueue k -> PriorityQueue k
    -- Remove the least queue element and return it:
    dequeue :: PriorityQueue k -> (k, PriorityQueue k)
    dequeue pq = (getMin pq, pop pq)
    contents :: PriorityQueue k -> [k]
    contents pq = if (PriorityQueue.null pq) then []
                  else k:(contents pq') where (k, pq') = dequeue pq


instance (Ord k) => PriorityQueue (Set.Set k) where
    empty = Set.empty
    null = Set.null
    insert = Set.insert
    getMin = Set.findMin
    pop = Set.deleteMin 
    dequeue = Set.deleteFindMin
    contents = Set.toAscList

-- NB: should I use Int instead of Integer?
data (Ord k) => Heap k = EmptyHeap |
                         Heap {size :: !Integer,
                               key :: k,
                               left, right :: (Heap k)}


instance (Ord k) => PriorityQueue (Heap k) where
    empty = EmptyHeap

    null EmptyHeap = True
    null _ = False

    insert = insertHeap
    getMin = minHeap
    pop = popHeap


heapSize :: (Ord k) => Heap k -> Integer
heapSize EmptyHeap = 0
heapSize Heap {size = s} = s

insertHeap :: (Ord k) => Heap k -> k -> Heap k
insertHeap k EmptyHeap = Heap k EmptyHeap EmptyHeap
insertHeap k h@(Heap {key = k', size = s, left = h1', right = h2'}) =
    if heapSize h1' < heapSize h2' then
       Heap {key = minK, size = s+1, left = (recur h1'), right = h2'}
    else
       Heap {key = minK, size = s+1, left = h1', right = (recur h2')}
        where recur h' = insertHeap maxK h'
              minK = min k k'
              maxK = max k k'



-- Empty heaps have no minimum (it's an error to even try to find one)
minHeap :: (Ord k) => Heap k -> k
minHeap (Heap {key = k}) = k



-- Note that this may unbalance the heap...but if you work out some
-- cases you'll see that the worst-case depth is still logarithmic in
-- the total number of operations, and that moreover if you are hit
-- with the worst-case cost, you always decrease the "badness" of the
-- tree.  Another way of looking at it is that trying to rebalance the
-- tree up-front would (I believe) incur about as much cost as just
-- accepting that the tree might become temporarily unbalanced.

-- The key to the comment above is the observation that the tree never
-- increases in depth unless it is fully balanced...so if you have an
-- unbalanced tree and hit the worst-case, it must be because you
-- deleted an element on the longest path in the tree.  Think
-- amortized analysis.

popHeap :: (Ord k) => Heap k -> Heap k
popHeap Heap {left = EmptyHeap, right = h'} = h'
popHeap Heap {right = EmptyHeap, left = h'} = h'
popHeap [EMAIL PROTECTED] {left = [EMAIL PROTECTED] {key = lk}, right = [EMAIL PROTECTED] {key = rk}} =
    if lk < rk then
       h {key = lk, size = (size h)-1, left=popHeap l}
    else
       h {key = rk, size = (size h)-1, right=popHeap r}

Reply via email to