- Add code to visualize an instance and matching as a graph (bipartite, rather
[match/match.git] / program / RandomizedMonad.hs
CommitLineData
967c39ef
MM
1module RandomizedMonad (
2 Randomized,
3 runRandom, runRandomStd, runRandomNewStd,
4 mrandomR, mrandom,
5 withProb,
6 filterRandomized
7) where
8import System.Random
9
10-- Needs -XRank2Types
11newtype Randomized a = Randomized (forall g. RandomGen g => (g -> a))
12
13-- This implementation splits the RandomGen over and over.
14-- It would also be possible to serialize everything and use a single RandomGen.
15instance Monad Randomized where
16 ma >>= amb = Randomized (\g -> let
17 (g1, g2) = split g
18 Randomized fa = ma
19 a = fa g1
20 Randomized fb = amb a
21 in fb g2
22 )
23 return x = Randomized (const x)
24
25runRandom :: RandomGen g => g -> Randomized a -> a
26runRandom g (Randomized fa) = fa g
27
28-- Conveniences
29runRandomStd :: Randomized a -> IO a
30runRandomStd ra = do
31 g <- getStdGen
32 return $ runRandom g ra
33
34runRandomNewStd :: Randomized a -> IO a
35runRandomNewStd ra = do
36 g <- newStdGen
37 return $ runRandom g ra
38
39-- Monadic versions of random and randomR (to generate primitive-ish values)
40mrandomR :: Random a => (a, a) -> Randomized a
41mrandomR lohi = Randomized (\g -> fst (randomR lohi g))
42mrandom :: Random a => Randomized a
43mrandom = Randomized (\g -> fst (random g))
44
45chooseCase :: Double -> [(Double, a)] -> a -> a
46chooseCase val ifCs elseR = case ifCs of
47 [] -> elseR
48 (cutoff, theR):ifCt -> if val < cutoff
49 then theR
50 else chooseCase (val - cutoff) ifCt elseR
51
52withProb :: [(Double, Randomized a)] -> Randomized a -> Randomized a
53withProb ifCs elseR = do
54 val <- mrandom
55 chooseCase val ifCs elseR
56
57-- Keep trying until we get what we want.
58filterRandomized :: (a -> Bool) -> Randomized a -> Randomized a
59filterRandomized f ra = do
60 a <- ra
61 if f a then return a else filterRandomized f ra