<table cellspacing="0" cellpadding="0" border="0" ><tr><td valign="top" style="font: inherit;">I'm using the code below to generate random days of the week [Monday..Sunday].<br><br>Is there a better/shorter way to do this?<br><br>Michael<br><br>==============<br><br>[michael@localhost ~]$ ghci dow<br>GHCi, version 6.10.1: http://www.haskell.org/ghc/ :? for help<br>Loading package ghc-prim ... linking ... done.<br>Loading package integer ... linking ... done.<br>Loading package base ... linking ... done.<br>[1 of 1] Compiling Main ( dow.hs, interpreted )<br>Ok, modules loaded: Main.<br>*Main> random (mkStdGen 100) :: (DayOfWeek, StdGen)<br>Loading package old-locale-1.0.0.1 ... linking ... done.<br>Loading package old-time-1.0.0.1 ... linking ... done.<br>Loading package random-1.0.0.1 ... linking ... done.<br>(Friday,4041414 40692)<br>*Main> random (mkStdGen 123) ::
(DayOfWeek, StdGen)<br>(Tuesday,4961736 40692)<br>*Main><br><br>==============<br><br>import System.Random<br><br>data DayOfWeek<br> = Monday<br> | Tuesday<br> | Wednesday<br> | Thursday<br> | Friday<br> | Saturday<br> | Sunday<br> deriving (Show, Read, Eq, Enum, Ord, Bounded)<br><br>instance Random DayOfWeek where<br> randomR (a,b) g = <br> case (randomIvalInteger (toInteger (dow2Int a), toInteger (dow2Int b)) g) of<br> (x, g) -> (int2Dow x, g)<br> where<br> dow2Int Monday = 0<br> dow2Int Tuesday = 1<br> dow2Int Wednesday
= 2<br> dow2Int Thursday = 3<br> dow2Int Friday = 4<br> dow2Int Saturday = 5<br> dow2Int Sunday = 6<br><br> int2Dow 0 = Monday<br> int2Dow 1 = Tuesday<br> int2Dow 2 = Wednesday<br> int2Dow 3 = Thursday<br> int2Dow 4 = Friday<br> int2Dow 5 = Saturday<br> int2Dow 6 = Sunday<br><br> random g = randomR (minBound,maxBound) g<br><br>randomIvalInteger :: (RandomGen g, Num a) => (Integer, Integer) -> g -> (a, g)<br>randomIvalInteger
(l,h) rng<br> | l > h = randomIvalInteger (h,l) rng<br> | otherwise = case (f n 1 rng) of (v, rng') -> (fromInteger (l + v `mod` k), rng')<br> where<br> k = h - l + 1<br> b = 2147483561<br> n = iLogBase b k<br><br> f 0 acc g = (acc, g)<br> f n acc g = <br> let<br> (x,g') = next g<br> in<br> f (n-1) (fromIntegral x + acc * b) g'<br><br>iLogBase :: Integer -> Integer -> Integer<br>iLogBase b i = if i < b then 1 else 1 + iLogBase b (i `div` b)<br><br><br><br> <br><br></td></tr></table><br>