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}