module Test.Framework.Seed where

import Test.Framework.Utilities

import System.Random (StdGen, mkStdGen, randomIO)

import Data.Char ( toLower )


data Seed = FixedSeed Int
          | RandomSeed

instance Show Seed where
    show :: Seed -> String
show Seed
RandomSeed    = String
"random"
    show (FixedSeed Int
n) = Int -> String
forall a. Show a => a -> String
show Int
n

instance Read Seed where
    readsPrec :: Int -> ReadS Seed
readsPrec Int
prec String
xs = if (Char -> Char) -> ShowS
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower String
random_prefix String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"random"
                        then [(Seed
RandomSeed, String
rest)]
                        else ((Int, String) -> (Seed, String))
-> [(Int, String)] -> [(Seed, String)]
forall a b. (a -> b) -> [a] -> [b]
map (Int -> Seed
FixedSeed (Int -> Seed) -> (Int, String) -> (Seed, String)
forall a c b. (a -> c) -> (a, b) -> (c, b)
`onLeft`) (Int -> ReadS Int
forall a. Read a => Int -> ReadS a
readsPrec Int
prec String
xs)
      where (String
random_prefix, String
rest) = Int -> String -> (String, String)
forall a. Int -> [a] -> ([a], [a])
splitAt Int
6 String
xs

-- | Given a 'Seed', returns a new random number generator based on that seed and the
-- actual numeric seed that was used to build that generator, so it can be recreated.
newSeededStdGen :: Seed -> IO (StdGen, Int)
newSeededStdGen :: Seed -> IO (StdGen, Int)
newSeededStdGen (FixedSeed Int
seed) = (StdGen, Int) -> IO (StdGen, Int)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ((StdGen, Int) -> IO (StdGen, Int))
-> (StdGen, Int) -> IO (StdGen, Int)
forall a b. (a -> b) -> a -> b
$ (Int -> StdGen
mkStdGen Int
seed, Int
seed)
newSeededStdGen Seed
RandomSeed = IO (StdGen, Int)
newStdGenWithKnownSeed

newStdGenWithKnownSeed :: IO (StdGen, Int)
newStdGenWithKnownSeed :: IO (StdGen, Int)
newStdGenWithKnownSeed = do
    Int
seed <- IO Int
forall a (m :: * -> *). (Random a, MonadIO m) => m a
randomIO
    (StdGen, Int) -> IO (StdGen, Int)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> StdGen
mkStdGen Int
seed, Int
seed)