module Game.LambdaHack.Strategy
( Strategy(..), liftFrequency, (.|), reject, (.=>), only
) where
import Control.Monad
import Game.LambdaHack.Utils.Frequency
newtype Strategy a = Strategy { runStrategy :: [Frequency a] }
deriving Show
instance Monad Strategy where
return x = Strategy $ return $ uniformFreq "Strategy_return" [x]
m >>= f = Strategy $
filter (not . nullFreq)
[ toFreq "Strategy_bind" [ (p * q, b)
| (p, a) <- runFrequency x
, y <- runStrategy (f a)
, (q, b) <- runFrequency y
]
| x <- runStrategy m ]
instance MonadPlus Strategy where
mzero = Strategy []
mplus (Strategy xs) (Strategy ys) = Strategy (xs ++ ys)
liftFrequency :: Frequency a -> Strategy a
liftFrequency f =
Strategy $ filter (not . nullFreq) $ return f
infixr 2 .|
(.|) :: Strategy a -> Strategy a -> Strategy a
(.|) = mplus
reject :: Strategy a
reject = mzero
infix 3 .=>
(.=>) :: Bool -> Strategy a -> Strategy a
p .=> m | p = m
| otherwise = mzero
only :: (a -> Bool) -> Strategy a -> Strategy a
only p s = do
x <- s
p x .=> return x