结合RandT和MaybeT

时间:2014-11-19 05:36:28

标签: haskell monad-transformers

我有一个简单的函数,使用Control.Monad.Random来创建一个可以对随机数进行采样的函数。

import Control.Monad.Random       
import Data.Random         

unif_bound :: (RandomGen g, Monad m) => Double -> Double -> RandT g m Double
unif_bound lb ub = getRandomR (lb,ub)

并且,我运行此操作以在GHCI中生成随机数:

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

但是,我想修改此代码以检查lb < ub,并将其包装在MaybeT中。我们的想法是在lb > ub应该返回Nothing的地方进行抽样。我意识到这是monad变压器的用武之地,但我之前从未使用过,也不知道从哪里开始。

作为参考,RandT定义为

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

谢谢!

1 个答案:

答案 0 :(得分:1)

您可以大致概括您的功能类型:

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

请注意,您可以将MaybeT (return Nothing)替换为fail "",因为这是MaybeT m的monad实例中定义失败的方式,但这不是很好。用法:

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

IOMonadRandom的一个实例,因此如果您只是在解释器中进行测试,则无需使用RandT