[project @ 2005-07-29 17:03:37 by ross]
[ghc-base.git] / Data / Queue.hs
1 -----------------------------------------------------------------------------
2 -- |
3 -- Module      :  Data.Queue
4 -- Copyright   :  (c) The University of Glasgow 2002
5 -- License     :  BSD-style (see the file libraries/base/LICENSE)
6 -- 
7 -- Maintainer  :  libraries@haskell.org
8 -- Stability   :  experimental
9 -- Portability :  portable
10 --
11 -- Queues with constant time operations, from
12 -- /Simple and efficient purely functional queues and deques/,
13 -- by Chris Okasaki, /JFP/ 5(4):583-592, October 1995.
14 --
15 -----------------------------------------------------------------------------
16
17 module Data.Queue
18 {-# DEPRECATED "Use Data.Sequence instead: it's faster and has more operations" #-}
19         (Queue,
20         -- * Primitive operations
21         -- | Each of these requires /O(1)/ time in the worst case.
22         emptyQueue, addToQueue, deQueue,
23         -- * Queues and lists
24         listToQueue, queueToList
25     ) where
26
27 import Prelude -- necessary to get dependencies right
28 import Data.Typeable
29
30 -- | The type of FIFO queues.
31 data Queue a = Q [a] [a] [a]
32
33 #include "Typeable.h"
34 INSTANCE_TYPEABLE1(Queue,queueTc,"Queue")
35
36 -- Invariants for Q xs ys xs':
37 --      length xs = length ys + length xs'
38 --      xs' = drop (length ys) xs       -- in fact, shared (except after fmap)
39 -- The queue then represents the list xs ++ reverse ys
40
41 instance Functor Queue where
42         fmap f (Q xs ys xs') = Q (map f xs) (map f ys) (map f xs')
43         -- The new xs' does not share the tail of the new xs, but it does
44         -- share the tail of the old xs, so it still forces the rotations.
45         -- Note that elements of xs' are ignored.
46
47 -- | The empty queue.
48 emptyQueue :: Queue a
49 emptyQueue = Q [] [] []
50
51 -- | Add an element to the back of a queue.
52 addToQueue :: Queue a -> a -> Queue a
53 addToQueue (Q xs ys xs') y = makeQ xs (y:ys) xs'
54
55 -- | Attempt to extract the front element from a queue.
56 -- If the queue is empty, 'Nothing',
57 -- otherwise the first element paired with the remainder of the queue.
58 deQueue :: Queue a -> Maybe (a, Queue a)
59 deQueue (Q [] _ _) = Nothing
60 deQueue (Q (x:xs) ys xs') = Just (x, makeQ xs ys xs')
61
62 -- Assuming
63 --      length ys <= length xs + 1
64 --      xs' = drop (length ys - 1) xs
65 -- construct a queue respecting the invariant.
66 makeQ :: [a] -> [a] -> [a] -> Queue a
67 makeQ xs ys [] = listToQueue (rotate xs ys [])
68 makeQ xs ys (_:xs') = Q xs ys xs'
69
70 -- Assuming length ys = length xs + 1,
71 --      rotate xs ys zs = xs ++ reverse ys ++ zs
72 rotate :: [a] -> [a] -> [a] -> [a]
73 rotate [] (y:_) zs = y : zs             -- the _ here must be []
74 rotate (x:xs) (y:ys) zs = x : rotate xs ys (y:zs)
75
76 -- | A queue with the same elements as the list.
77 listToQueue :: [a] -> Queue a
78 listToQueue xs = Q xs [] xs
79
80 -- | The elements of a queue, front first.
81 queueToList :: Queue a -> [a]
82 queueToList (Q xs ys _) = xs ++ reverse ys