我有一个简单的函数,使用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)
谢谢!
最佳答案
您可以相当概括一下函数的类型:
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 ""
,因为这是在monad实例中为MaybeT m
定义fail的方式,但这不是很好。用法:>runMaybeT $ unif_bound 1 10
Just 2
>runMaybeT $ unif_bound 400 1
Nothing
IO
是MonadRandom
的一个实例,因此,如果您只是在解释器中进行测试,则无需摆弄RandT
。