packages feed

monad-bayes-1.2.0: src/Control/Monad/Bayes/Density/State.hs

{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}

-- |
-- Slower than Control.Monad.Bayes.Density.Free, so not used by default,
-- but more elementary to understand. Just uses standard
-- monad transformer techniques.
module Control.Monad.Bayes.Density.State where

import Control.Monad.Bayes.Class (MonadDistribution (random))
import Control.Monad.State (MonadState (get, put), StateT, evalStateT)
import Control.Monad.Writer

newtype DensityT m a = DensityT {getDensityT :: WriterT [Double] (StateT [Double] m) a} deriving newtype (Functor, Applicative, Monad)

instance MonadTrans DensityT where
  lift = DensityT . lift . lift

instance (Monad m) => MonadState [Double] (DensityT m) where
  get = DensityT $ lift $ get
  put = DensityT . lift . put

instance (Monad m) => MonadWriter [Double] (DensityT m) where
  tell = DensityT . tell
  listen = DensityT . listen . getDensityT
  pass = DensityT . pass . getDensityT

instance (MonadDistribution m) => MonadDistribution (DensityT m) where
  random = do
    trace <- get
    x <- case trace of
      [] -> random
      r : xs -> put xs >> pure r
    tell [x]
    pure x

runDensityT :: (Monad m) => DensityT m b -> [Double] -> m (b, [Double])
runDensityT (DensityT m) = evalStateT (runWriterT m)