Combining RandT and MaybeT

I have a simple function that uses Control.Monad.Random to create a function that can display a random number.

 import Control.Monad.Random import Data.Random unif_bound :: (RandomGen g, Monad m) => Double -> Double -> RandT gm Double unif_bound lb ub = getRandomR (lb,ub) 

And I run this to generate random numbers in GHCI like:

  > gen <- newStdGen > runRandT (unif_bound 1.0 3.0) gen (1.7569726469904563,1700403094 44073136) > runRandT (unif_bound 3.0, 1.0) gen (1.7569726469904563,1700403094 44073136) 

However, I would like to modify this code to check that lb < ub , and wrap it in MaybeT. The idea is to fetch where lb > ub should return Nothing . I understand that this is where monad transformers occur, but I had never used them before and did not know where to start.

For reference, RandT is defined as

 -- | A monad transformer which adds a random number generator to an -- existing monad. newtype RandT gma = RandT (StateT gma) deriving (Functor, Monad, MonadTrans, MonadIO, MonadFix, MonadReader r, MonadWriter w) 

Thanks!

+5
source share
1 answer

You can generalize the type of your function a bit:

 unif_bound :: (Random a, Ord a, MonadRandom m) => a -> a -> MaybeT ma unif_bound lb ub | lb > ub = MaybeT (return Nothing) | otherwise = getRandomR (lb,ub) 

Please note that you can replace MaybeT (return Nothing) with fail "" , because this is how the error is defined in the monad instance for MaybeT m , but it is not very nice. Using:

 >runMaybeT $ unif_bound 1 10 Just 2 >runMaybeT $ unif_bound 400 1 Nothing 

IO is an instance of MonadRandom , so you don't have to bother with RandT if you are just testing in the interpreter.

+1
source

Source: https://habr.com/ru/post/1207191/


All Articles