From ee4f5e6ee0529970d117c5964f61e934a1c51dc5 Mon Sep 17 00:00:00 2001 From: Mitchell Rosen Date: Sat, 13 Jan 2024 13:51:13 -0500 Subject: [PATCH] doc tweaks --- queues.cabal | 2 +- src/Queue.hs | 41 +++++++++++++++++++++++++++++++++-------- src/Queue/Ephemeral.hs | 40 ++++++++++++++++++++++++++++++++-------- 3 files changed, 66 insertions(+), 17 deletions(-) diff --git a/queues.cabal b/queues.cabal index 7dcff29..ff94e20 100644 --- a/queues.cabal +++ b/queues.cabal @@ -26,7 +26,7 @@ description: +=================+======================+====================+ | @enqueue@ | \(\mathcal{O}(1)\) | \(\mathcal{O}(1)\) | +-----------------+----------------------+--------------------+ - | @dequeue@ | \(\mathcal{O}(1)^⧧\) | \(\mathcal{O}(1)\) | + | @dequeue@ | \(\mathcal{O}(1)^*\) | \(\mathcal{O}(1)\) | +-----------------+----------------------+--------------------+ . * \(^*\) Amortized, under ephemeral usage only. diff --git a/src/Queue.hs b/src/Queue.hs index c7afbc3..0d8ae92 100644 --- a/src/Queue.hs +++ b/src/Queue.hs @@ -35,6 +35,7 @@ module Queue -- ** Initialization empty, singleton, + fromList, -- * Basic interface enqueue, @@ -51,8 +52,7 @@ module Queue map, traverse, - -- * List conversions - fromList, + -- * Conversions toList, ) where @@ -64,6 +64,9 @@ import GHC.Exts (Any) import Unsafe.Coerce (unsafeCoerce) import Prelude hiding (foldMap, length, map, span, traverse) +------------------------------------------------------------------------------------------------------------------------ +-- Queue type and instances + -- | A queue data structure with \(\mathcal{O}(1)\) (worst-case) operations. data Queue a = Q @@ -128,6 +131,9 @@ instance Traversable Queue where traverse = Queue.traverse +------------------------------------------------------------------------------------------------------------------------ +-- Patterns + -- | An empty queue. pattern Empty :: Queue a pattern Empty <- (dequeue -> Nothing) @@ -138,8 +144,9 @@ pattern Front x xs <- (dequeue -> Just (x, xs)) {-# COMPLETE Empty, Front #-} --- Queue smart constructor. --- +------------------------------------------------------------------------------------------------------------------------ +-- Internal smart constructor utils + -- `queue xs ys zs` is always called when |zs| = |xs| - |ys| + 1 (i.e. just after a enqueue or dequeue) makeQueue :: [a] -> [a] -> Schedule -> Queue a makeQueue xs ys = \case @@ -153,6 +160,9 @@ rotate (NonEmptyList y ys) zs = \case [] -> y : zs x : xs -> x : rotate ys (y : zs) xs +------------------------------------------------------------------------------------------------------------------------ +-- Initialization + -- | An empty queue. empty :: Queue a empty = @@ -165,6 +175,14 @@ singleton x = where xs = [x] +-- | \(\mathcal{O}(1)\). Construct a queue from a list. The head of the list corresponds to the front of the queue. +fromList :: [a] -> Queue a +fromList xs = + Q xs [] (schedule xs) + +------------------------------------------------------------------------------------------------------------------------ +-- Basic interface + -- | \(\mathcal{O}(1)\). Enqueue an element at the back of a queue, to be dequeued last. enqueue :: a -> Queue a -> Queue a enqueue y (Q xs ys zs) = @@ -176,6 +194,9 @@ dequeue = \case Q [] _ _ -> Nothing Q (x : xs) ys zs -> Just (x, makeQueue xs ys zs) +------------------------------------------------------------------------------------------------------------------------ +-- Extended interface + -- | \(\mathcal{O}(1)\). Enqueue an element at the front of a queue, to be dequeued next. enqueueFront :: a -> Queue a -> Queue a enqueueFront x (Q xs ys zs) = @@ -200,12 +221,18 @@ span p = | p x -> go (enqueue x acc) xs | otherwise -> (acc, queue) +------------------------------------------------------------------------------------------------------------------------ +-- Queries + -- | \(\mathcal{O}(1)\). Is a queue empty? isEmpty :: Queue a -> Bool isEmpty = \case Q [] _ _ -> True _ -> False +------------------------------------------------------------------------------------------------------------------------ +-- Transformations + -- | \(\mathcal{O}(n)\). Apply a function to every element in a queue. map :: (a -> b) -> Queue a -> Queue b map f = @@ -216,10 +243,8 @@ traverse :: (Applicative f) => (a -> f b) -> Queue a -> f (Queue b) traverse f = fmap fromList . Traversable.traverse f . toList --- | \(\mathcal{O}(1)\). Construct a queue from a list. The head of the list corresponds to the front of the queue. -fromList :: [a] -> Queue a -fromList xs = - Q xs [] (schedule xs) +------------------------------------------------------------------------------------------------------------------------ +-- Conversions -- | \(\mathcal{O}(n)\). Construct a list from a queue. The head of the list corresponds to the front of the queue. toList :: Queue a -> [a] diff --git a/src/Queue/Ephemeral.hs b/src/Queue/Ephemeral.hs index 36ddb47..176ed6b 100644 --- a/src/Queue/Ephemeral.hs +++ b/src/Queue/Ephemeral.hs @@ -1,4 +1,4 @@ --- | A queue data structure with \(\mathcal{O}(1)^⧧\) (amortized under ephemeral usage only) operations, as described in +-- | A queue data structure with \(\mathcal{O}(1)^*\) (amortized under ephemeral usage only) operations, as described in -- -- * Okasaki, Chris. \"Simple and efficient purely functional queues and deques.\" /Journal of functional programming/ 5.4 (1995): 583-592. -- * Okasaki, Chris. /Purely Functional Data Structures/. Diss. Princeton University, 1996. @@ -35,6 +35,7 @@ module Queue.Ephemeral -- ** Initialization empty, singleton, + fromList, -- * Basic interface enqueue, @@ -51,8 +52,7 @@ module Queue.Ephemeral map, traverse, - -- * List conversions - fromList, + -- * Conversions toList, ) where @@ -61,6 +61,9 @@ import Data.Foldable qualified as Foldable import Data.Traversable qualified as Traversable import Prelude hiding (foldMap, length, map, span, traverse) +------------------------------------------------------------------------------------------------------------------------ +-- Queue type and instances + -- | A queue data structure with \(\mathcal{O}(1)^⧧\) (amortized under ephemeral usage only) operations. data EphemeralQueue a = Q [a] [a] @@ -90,6 +93,9 @@ instance Traversable EphemeralQueue where traverse = traverse +------------------------------------------------------------------------------------------------------------------------ +-- Patterns + -- | An empty queue. pattern Empty :: EphemeralQueue a pattern Empty <- (dequeue -> Nothing) @@ -100,6 +106,9 @@ pattern Front x xs <- (dequeue -> Just (x, xs)) {-# COMPLETE Empty, Front #-} +------------------------------------------------------------------------------------------------------------------------ +-- Initialization + -- | An empty queue. empty :: EphemeralQueue a empty = @@ -110,12 +119,20 @@ singleton :: a -> EphemeralQueue a singleton x = Q [x] [] +-- | \(\mathcal{O}(1)\). Construct a queue from a list. The head of the list corresponds to the front of the queue. +fromList :: [a] -> EphemeralQueue a +fromList xs = + Q xs [] + +------------------------------------------------------------------------------------------------------------------------ +-- Basic interface + -- | \(\mathcal{O}(1)\). Enqueue an element at the back of a queue, to be dequeued last. enqueue :: a -> EphemeralQueue a -> EphemeralQueue a enqueue y (Q xs ys) = Q xs (y : ys) --- | \(\mathcal{O}(1)^⧧\) front, \(\mathcal{O}(1)^⧧\) rest. Dequeue an element from the front of a queue. +-- | \(\mathcal{O}(1)^*\) front, \(\mathcal{O}(1)^*\) rest. Dequeue an element from the front of a queue. dequeue :: EphemeralQueue a -> Maybe (a, EphemeralQueue a) dequeue = \case Q [] ys -> @@ -124,6 +141,9 @@ dequeue = \case x : xs -> Just (x, Q xs []) Q (x : xs) ys -> Just (x, Q xs ys) +------------------------------------------------------------------------------------------------------------------------ +-- Extended interface + -- | \(\mathcal{O}(1)\). Enqueue an element at the front of a queue, to be dequeued next. enqueueFront :: a -> EphemeralQueue a -> EphemeralQueue a enqueueFront x (Q xs ys) = @@ -145,12 +165,18 @@ span p = | p x -> go (enqueue x acc) xs | otherwise -> (acc, enqueueFront x xs) +------------------------------------------------------------------------------------------------------------------------ +-- Queries + -- | \(\mathcal{O}(1)\). Is a queue empty? isEmpty :: EphemeralQueue a -> Bool isEmpty = \case Q [] [] -> True _ -> False +------------------------------------------------------------------------------------------------------------------------ +-- Transformations + -- | \(\mathcal{O}(n)\). Apply a function to every element in a queue. map :: (a -> b) -> EphemeralQueue a -> EphemeralQueue b map = @@ -170,10 +196,8 @@ traverse f (Q xs ys) = [] -> pure [] z : zs -> flip (:) <$> go zs <*> f z --- | \(\mathcal{O}(1)\). Construct a queue from a list. The head of the list corresponds to the front of the queue. -fromList :: [a] -> EphemeralQueue a -fromList xs = - Q xs [] +------------------------------------------------------------------------------------------------------------------------ +-- Conversions -- | \(\mathcal{O}(n)\). Construct a list from a queue. The head of the list corresponds to the front of the queue. toList :: EphemeralQueue a -> [a]