packages feed

monad-bayes-1.1.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 Density m a = Density {runDensity :: WriterT [Double] (StateT [Double] m) a} deriving newtype (Functor, Applicative, Monad)

instance MonadTrans Density where
  lift = Density . lift . lift

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

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

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

density :: Monad m => Density m b -> [Double] -> m (b, [Double])
density (Density m) = evalStateT (runWriterT m)