2014-11-19 10 views
5

Ich habe eine einfache Funktion Control.Monad.Random zu verwenden, um eine Funktion zu erstellen, die eine zufällige Zahl abtasten kann.Kombinieren von RandT und MaybeT

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) 

Und ich betreibe diese Zufallszahlen in GHCI zu erzeugen, wie:

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

Allerdings würde Ich mag diesen Code modifizieren, dass lb < ub zu überprüfen, und wickeln diese in einem MaybeT. Die Idee ist, dass die Stichprobe lb > ubNothing zurückgeben sollte. Mir ist klar, dass hier die Monad-Transformatoren hereinkommen, aber ich habe noch nie zuvor eine verwendet und bin mir nicht sicher, wo ich anfangen soll.

Als Referenz wird RandT als

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

Dank!

+1

http://en.wikibooks.org/wiki/Haskell/Monad_transformers. Sie können auch einfach ein 'RandT g m (Maybe Double)' - Transformatoren sind manchmal übertrieben, und klingt, als ob sie wahrscheinlich für Ihren Fall sind. Aber eine gute Gelegenheit zu lernen! – luqui

Antwort

1

Sie die Art Ihrer Funktion verallgemeinern kann ziemlich viel:

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) 

Beachten Sie, dass MaybeT (return Nothing) mit fail "" ersetzen konnte, weil das ist, wie für MaybeT m in der Monade Instanz definiert ist, fail, aber dies ist nicht Sehr schön. Verbrauch:

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

IO ist eine Instanz MonadRandom, so brauchen Sie nicht mit RandT Geige, wenn Sie nur im Interpreter testen.