packages feed

HFrequencyQueue-0.2.0.0: src/FrequencyQueue.hs

{-|
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_)