{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeFamilies #-}
module FRP.Rhine.ClSF.Random
  ( module FRP.Rhine.ClSF.Random
  , module X
  )
  where
import Control.Monad.IO.Class
import System.Random (newStdGen)
import Control.Monad.Random
import Control.Monad.Trans.MSF.Except (performOnFirstSample)
import qualified Control.Monad.Trans.MSF.Random as MSF
import Control.Monad.Trans.MSF.Random as X hiding (runRandS, evalRandS, getRandomS, getRandomRS, getRandomRS_)
import FRP.Rhine.ClSF.Core
import FRP.Rhine.ClSF.Random.Util
runRandS
  :: (RandomGen g, Monad m)
  => ClSF (RandT g m) cl a     b
  -> g 
  -> ClSF          m  cl a (g, b)
runRandS clsf g = MSF.runRandS (morphS commuteReaderRand clsf) g
evalRandS
  :: (RandomGen g, Monad m)
  => ClSF (RandT g m) cl a b
  -> g
  -> ClSF          m  cl a b
evalRandS clsf g = runRandS clsf g >>> arr snd
execRandS
  :: (RandomGen g, Monad m)
  => ClSF (RandT g m) cl a b
  -> g
  -> ClSF          m  cl a g
execRandS clsf g = runRandS clsf g >>> arr fst
evalRandIOS
  :: Monad m
  =>     ClSF (RandT StdGen m) cl a b
  -> IO (ClSF               m  cl a b)
evalRandIOS clsf = do
  g <- newStdGen
  return $ evalRandS clsf g
evalRandIOS'
  :: MonadIO m
  => ClSF (RandT StdGen m) cl a b
  -> ClSF               m  cl a b
evalRandIOS' = performOnFirstSample . liftIO . evalRandIOS
getRandomS
  :: (MonadRandom m, Random a)
  => Behaviour m time a
getRandomS = constMCl getRandom
getRandomRS
  :: (MonadRandom m, Random a)
  => BehaviourF m time (a, a) a
getRandomRS = arrMCl getRandomR
getRandomRS_
  :: (MonadRandom m, Random a)
  => (a, a)
  -> Behaviour m time a
getRandomRS_ = constMCl . getRandomR