{-| Module : FrequencyQueue Description : Main module for FrequencyQueue Copyright : (c) Andrea Bellandi 2014 License : GPL-3 Maintainer : bellaz89@gmai.com Stability : experimental Portability : POSIX This module export the interface of FrequencyQueue. -} module FrequencyQueue( -- *Types FrequencyQueue(), -- *Functions -- **Creation functions newFrequencyQueue, -- **Basic properties length, probabilityUnit, -- **Pop-push functions pushBack, popBack, popBackMax, popBackMin, getRandom, getRandomPop, -- **Iterative functions mapWprobability, foldWprobability, -- **Unsafe interface popBackUnsafe, popBackMaxUnsafe, popBackMinUnsafe, getRandomUnsafe, getRandomPopUnsafe) where import Prelude hiding (length) import System.IO.Unsafe(unsafePerformIO) import FrequencyQueue.IO(FrequencyQueue) import qualified FrequencyQueue.IO as FQIO import Control.Monad(Functor(..)) import Data.Foldable(Foldable(..)) instance Functor FrequencyQueue where fmap fun queue_ = mapWprobability (\(el,prob) -> (fun(el),prob)) queue_ instance Foldable FrequencyQueue where foldr fun b0 queue_ = foldWprobability (\b (el,_) -> fun el b ) b0 queue_ -- |Create a new FrequencyQueue with a seed newFrequencyQueue :: Int -> FrequencyQueue a newFrequencyQueue seed = (unsafePerformIO . FQIO.newFrequencyQueue) seed -- |Return the number of elements in the queue length :: FrequencyQueue a -> Int length queue_ = (unsafePerformIO . FQIO.length) queue_ -- |Return the sum of all elements' probabilities passed to the queue probabilityUnit :: FrequencyQueue a -> Int probabilityUnit queue_ = (unsafePerformIO . FQIO.probabilityUnit) queue_ -- |Push an element a in the queue with a corresponding relative probability pushBack :: FrequencyQueue a -> a -> Int -> FrequencyQueue a pushBack queue_ element_ probability_ = unsafePerformIO $ do newqueue_ <- FQIO.cloneFrequencyQueue queue_ FQIO.pushBack newqueue_ element_ probability_ return newqueue_ -- |Pop an element of the queue. Return Nothing if the queue is empty popBack :: FrequencyQueue a -> Maybe ((a, Int), FrequencyQueue a) popBack queue_ = if (length queue_) == 0 then Nothing else Just (popBackUnsafe queue_) -- |Pop the element of the queue that have the biggest relative probability. -- Return Nothing if the queue is empty popBackMax :: FrequencyQueue a -> Maybe ((a, Int), FrequencyQueue a) popBackMax queue_ = if (length queue_) == 0 then Nothing else Just (popBackMaxUnsafe queue_) -- |Pop the element of the queue that have the smallest relative probability. -- Return Nothing if the queue is empty popBackMin :: FrequencyQueue a -> Maybe ((a, Int), FrequencyQueue a) popBackMin queue_ = if (length queue_) == 0 then Nothing else Just (popBackMinUnsafe queue_) -- |Return a random element from the queue using its relative probability. -- Return Nothing if the queue is empty getRandom :: FrequencyQueue a -> Maybe ((a, Int), FrequencyQueue a) getRandom queue_ = if (length queue_) == 0 then Nothing else Just (getRandomUnsafe queue_) -- |Pop a random element from the queue using its relative probability. -- Return Nothing if the queue is empty getRandomPop :: FrequencyQueue a -> Maybe ((a, Int), FrequencyQueue a) getRandomPop queue_ = if (length queue_) == 0 then Nothing else Just (getRandomPopUnsafe queue_) -- |Return a new queue with the elements and relative probability mapped -- by the function provided mapWprobability :: ((a, Int) -> (b, Int)) -> FrequencyQueue a -> FrequencyQueue b mapWprobability fun queue_ = unsafePerformIO $ FQIO.mapWprobability fun queue_ -- |Return a folded value made by an initial value b and a folding function -- evaluated on the entire queue. foldWprobability :: (b -> (a, Int) -> b) -> b -> FrequencyQueue a -> b foldWprobability fold_fun b0 queue_ = unsafePerformIO $ FQIO.foldWprobability fold_fun b0 queue_ -- |Pop an element of the queue. Fail if empty popBackUnsafe :: FrequencyQueue a -> ((a, Int), FrequencyQueue a) popBackUnsafe queue_ = unsafePerformIO $ do newqueue_ <- FQIO.cloneFrequencyQueue queue_ result <- FQIO.popBackUnsafe newqueue_ return (result, newqueue_) -- |Pop the element of the queue that have the biggest relative probability. -- Fail if empty popBackMaxUnsafe :: FrequencyQueue a -> ((a, Int), FrequencyQueue a) popBackMaxUnsafe queue_ = unsafePerformIO $ do newqueue_ <- FQIO.cloneFrequencyQueue queue_ result <- FQIO.popBackMaxUnsafe newqueue_ return (result, newqueue_) -- |Pop the element of the queue that have the smallest relative probability. -- Fail if empty popBackMinUnsafe :: FrequencyQueue a -> ((a, Int), FrequencyQueue a) popBackMinUnsafe queue_ = unsafePerformIO $ do newqueue_ <- FQIO.cloneFrequencyQueue queue_ result <- FQIO.popBackMinUnsafe newqueue_ return (result, newqueue_) -- |Pop the element of the queue that have the smallest relative probability. -- Fail if empty getRandomUnsafe :: FrequencyQueue a -> ((a, Int), FrequencyQueue a) getRandomUnsafe queue_ = unsafePerformIO $ do newqueue_ <- FQIO.cloneFrequencyQueue queue_ result <- FQIO.getRandomUnsafe newqueue_ return (result, newqueue_) -- |Pop a random element from the queue using its relative probability. -- Fail if empty getRandomPopUnsafe :: FrequencyQueue a -> ((a, Int), FrequencyQueue a) getRandomPopUnsafe queue_ = unsafePerformIO $ do newqueue_ <- FQIO.cloneFrequencyQueue queue_ result <- FQIO.getRandomPopUnsafe newqueue_ return (result, newqueue_)