module Control.Monad.Bayes.Free (
FreeSampler,
hoist,
interpret,
withRandomness,
withPartialRandomness,
runWith
) where
import Data.Functor.Identity
import Control.Monad.Trans
import Control.Monad.Writer
import Control.Monad.State
import Control.Monad.Trans.Free.Church
import Control.Monad.Bayes.Class
newtype SamF a = Random (Double -> a)
instance Functor SamF where
fmap f (Random k) = Random (f . k)
newtype FreeSampler m a = FreeSampler (FT SamF m a)
deriving(Functor,Applicative,Monad,MonadTrans)
runFreeSampler :: FreeSampler m a -> FT SamF m a
runFreeSampler (FreeSampler m) = m
instance Monad m => MonadFree SamF (FreeSampler m) where
wrap = FreeSampler . wrap . fmap runFreeSampler
instance Monad m => MonadSample (FreeSampler m) where
random = FreeSampler $ liftF (Random id)
hoist :: (Monad m, Monad n) => (forall x. m x -> n x) -> FreeSampler m a -> FreeSampler n a
hoist f (FreeSampler m) = FreeSampler (hoistFT f m)
interpret :: MonadSample m => FreeSampler m a -> m a
interpret (FreeSampler m) = iterT f m where
f (Random k) = random >>= k
withRandomness :: Monad m => [Double] -> FreeSampler m a -> m a
withRandomness randomness (FreeSampler m) = evalStateT (iterTM f m) randomness where
f (Random k) = do
xs <- get
case xs of
[] -> error "FreeSampler: the list of randomness was too short"
y:ys -> put ys >> k y
withPartialRandomness :: MonadSample m => [Double] -> FreeSampler m a -> m (a, [Double])
withPartialRandomness randomness (FreeSampler m) =
runWriterT $ evalStateT (iterTM f $ hoistFT lift m) randomness where
f (Random k) = do
xs <- get
x <- case xs of
[] -> random
y:ys -> put ys >> return y
tell [x]
k x
runWith :: MonadSample m => [Double] -> FreeSampler Identity a -> m (a, [Double])
runWith randomness m = withPartialRandomness randomness $ hoist (return . runIdentity) m