diff options
| author | pb <pb@9f8f72e9-4bf4-416e-b76e-7d4203597157> | 2010-03-28 21:42:11 +0000 |
|---|---|---|
| committer | pb <pb@9f8f72e9-4bf4-416e-b76e-7d4203597157> | 2010-03-28 21:42:11 +0000 |
| commit | 8bef12cb86af79420e61ce8cd60cfb7ae1e69953 (patch) | |
| tree | 4300c34a6e691821172b26f7a3220647c8af1a54 /examples | |
| parent | 2341aa600daac2c8afa366cd612a893580104a93 (diff) | |
git-svn-id: https://ssl.buetow.org/repos/hsbot/trunk@56 9f8f72e9-4bf4-416e-b76e-7d4203597157
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/example15.hs | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/examples/example15.hs b/examples/example15.hs new file mode 100644 index 0000000..945f9a8 --- /dev/null +++ b/examples/example15.hs @@ -0,0 +1,81 @@ +{- Author: Jeff Newbern + Maintainer: Jeff Newbern <jnewbern@nomaware.com> + Time-stamp: <Thu Jul 24 13:39:30 2003> + License: GPL +-} + +{- DESCRIPTION + +Example 15 - Using the State monad + +Usage: Compile the code and execute the command. + It will print two identical random values of type MyType. + The first value is computed without the State monad and + the second is computed using the State monad. + The MyType values are random but obey some internal + invariants: + o the Int value is in the range 1-100. + o the Char value is in the range 'a'-'z' + o the absolute value of the second Int value is + less than or equal to the value of the first Int value + +Try: ./ex15 +-} + +import Monad +import System +import IO +import Random +import Control.Monad.State + +-- This is the type that we want to generate random values of +data MyType = MT Int Bool Char Int deriving Show + +{- Without using the State monad, we would have to thread the + random number generator state by hand. The function would + look like this: +-} +makeRandomValue :: StdGen -> (MyType, StdGen) +makeRandomValue g = let (n,g1) = randomR (1,100) g + (b,g2) = random g1 + (c,g3) = randomR ('a','z') g2 + (m,g4) = randomR (-n,n) g3 + in (MT n b c m, g4) + +{- Using the State monad, we can define a function that returns + a random value and updates the random generator state at + the same time. +-} + +getAny :: (Random a) => State StdGen a +getAny = do g <- get + (x,g') <- return $ random g + put g' + return x + +-- similar to getAny, but it bounds the random value returned +getOne :: (Random a) => (a,a) -> State StdGen a +getOne bounds = do g <- get + (x,g') <- return $ randomR bounds g + put g' + return x + +{- Using the State monad with StdGen as the state, we can build + random complex types without manually threading the + random generator states through the code. +-} +makeRandomValueST :: StdGen -> (MyType, StdGen) +makeRandomValueST = runState (do n <- getOne (1,100) + b <- getAny + c <- getOne ('a','z') + m <- getOne (-n,n) + return (MT n b c m)) + +-- print a random value of MyType, showing the two implementations +-- are equivalent +main :: IO () +main = do g <- getStdGen + print $ fst $ makeRandomValue g + print $ fst $ makeRandomValueST g + +-- END OF FILE |
