packages feed

random-extras 0.1 → 0.2

raw patch · 2 files changed

+84/−14 lines, 2 filesdep +arraydep +randomdep −monad-loops

Dependencies added: array, random

Dependencies removed: monad-loops

Files

Control/Monad/Random/Extras.hs view
@@ -16,32 +16,58 @@   -- ** Shuffling   shuffle , shuffleSeq+  -- ** Sampling+, sample+, sampleSeq   -- ** Choice , choiceExtract , choiceExtractSeq , choice , choiceSeq+, choiceArray+  -- ** Choices+, choices+, choicesArray ) where -import Control.Monad (MonadPlus, liftM)-import Control.Monad.Loops (unfoldrM')-import Control.Monad.Random (MonadRandom, getRandomR)+import Control.Monad (liftM)+import Control.Monad.Random (MonadRandom, getRandomR, getRandomRs)+import System.Random (Random)+import Data.List (mapAccumL)+import Data.Maybe (fromJust) import qualified Data.Sequence as Seq import Data.Sequence ((><), ViewL((:<)))+import qualified Data.Array.IArray as Arr+import qualified Data.Array+import Data.Array.IArray ((!)) -extract :: [a] -> Int -> Maybe (a, [a])+(.:) :: (c -> c') -> (a -> b -> c) -> (a -> b -> c')+(.:) = (.).(.)++extract :: [a] -> Int -> Maybe ([a], a) extract s i | null r    = Nothing-            | otherwise = Just (b, a ++ c)+            | otherwise = Just (a ++ c, b)     where (a, r) = splitAt i s           (b : c) = r -extractSeq :: Seq.Seq a -> Int -> Maybe (a, Seq.Seq a)+extractSeq :: Seq.Seq a -> Int -> Maybe (Seq.Seq a, a) extractSeq s i | Seq.null r = Nothing-               | otherwise  = Just (b, a >< c)+               | otherwise  = Just (a >< c, b)     where (a, r) = Seq.splitAt i s            (b :< c) = Seq.viewl r +getRandomR' :: (MonadRandom m, Random a) => a -> a -> m a+getRandomR' = curry getRandomR++getRandomRNums :: (MonadRandom m, Random a, Num a) => [a] -> m [a]+getRandomRNums = mapM (getRandomR' 0)++backsaw :: Int -> [Int]+backsaw n = [n - 1, n - 2 .. 0]+          +-- Shuffling+ -- | Shuffle a list randomly. The method is based on Oleg Kiselyov's  -- /perfect shuffle/ <http://okmij.org/ftp/Haskell/perfect-shuffle.txt>, -- but much simpler because it uses existing data structures. The efficiency@@ -55,20 +81,43 @@ -- so it logically uses the same method. -- -- Complexity: O(n * log n)-shuffleSeq :: (MonadRandom m, MonadPlus f) => Seq.Seq a -> m (f a)-shuffleSeq = unfoldrM' choiceExtractSeq+shuffleSeq :: (MonadRandom m) => Seq.Seq a -> m [a]+shuffleSeq s = do+  samples <- getRandomRNums . backsaw $ Seq.length s+  return (shuffleSeq' s samples) +shuffleSeq' :: Seq.Seq a -> [Int] -> [a]+shuffleSeq' = snd .: mapAccumL (fromJust .: extractSeq)++-- Sampling++-- | Take a random sample from a list.+-- +-- Complexity: O(n + m * log n)+sample :: (MonadRandom m) => Int -> [a] -> m [a]+sample m = sampleSeq m . Seq.fromList++-- | Take a random sample from a sequence.+-- +-- Complexity: O(m * log n)+sampleSeq :: (MonadRandom m) => Int -> Seq.Seq a -> m [a]+sampleSeq m s = do+  samples <- getRandomRNums . take m . backsaw $ Seq.length s+  return (shuffleSeq' s samples)++-- Choice+ -- | Randomly choose and extract an element from a list. -- -- Complexity: O(n)-choiceExtract :: (MonadRandom m) => [a] -> m (Maybe (a, [a]))+choiceExtract :: (MonadRandom m) => [a] -> m (Maybe ([a], a)) choiceExtract [] = return Nothing choiceExtract xs = extract xs `liftM` getRandomR (0, length xs - 1)                      -- | Randomly choose and extract an element from a sequence. -- -- Complexity: O(log n)-choiceExtractSeq :: (MonadRandom m) => Seq.Seq a -> m (Maybe (a, Seq.Seq a))+choiceExtractSeq :: (MonadRandom m) => Seq.Seq a -> m (Maybe (Seq.Seq a, a)) choiceExtractSeq s | Seq.null s = return Nothing                    | otherwise  = extractSeq s `liftM` getRandomR (0, Seq.length s - 1) @@ -85,3 +134,23 @@ choiceSeq :: (MonadRandom m) => Seq.Seq a -> m a choiceSeq s | Seq.null s = error "Control.Monad.Random.Extras.choiceSeq: empty sequence"             | otherwise  = Seq.index s `liftM` getRandomR (0, Seq.length s - 1)++-- | Select a random element from an array.+--+-- Complexity: O(1).+choiceArray :: (MonadRandom m, Arr.IArray arr a, Arr.Ix i, Random i) => arr i a -> m a+choiceArray v = (v !) `liftM` getRandomR (Arr.bounds v)++-- Choices++-- | Select /m/ random elements from a list.+--+-- Complexity: O(m)+choices :: (MonadRandom m) => Int -> [a] -> m [a]+choices m xs = choicesArray m (Data.Array.listArray (1, length xs) xs)++-- | Select /m/ random elements from an array.+--+-- Complexity: O(m)+choicesArray :: (MonadRandom m, Arr.IArray arr a, Arr.Ix i, Random i) => Int -> arr i a -> m [a]+choicesArray m v = map (v !) `liftM` take m `liftM` getRandomRs (Arr.bounds v)
random-extras.cabal view
@@ -7,7 +7,7 @@ -- The package version. See the Haskell package versioning policy -- (http://www.haskell.org/haskellwiki/Package_versioning_policy) for -- standards guiding when and how versions should be incremented.-Version:             0.1+Version:             0.2  -- A short (one-line) description of the package. Synopsis:            Additional functions for random values.@@ -55,8 +55,9 @@   Build-depends:         base >=4 && <5,         containers ==0.3.*,-        MonadRandom ==0.1.*,-        monad-loops ==0.3.1.*+        array ==0.3.*,+        random ==1.0.0.*,+        MonadRandom ==0.1.*      -- Modules not exported by this package.   -- Other-modules: