-- | Tracing
module Numeric.Probability.Trace where

import qualified Numeric.Probability.Distribution as Dist
import qualified Numeric.Probability.Transition   as Trans
import qualified Numeric.Probability.Random       as Rnd

import Data.List (transpose)


-- * traces of distributions

type Trace a  = [a]
type Walk a   = a -> Trace a

type Space prob a  = Trace (Dist.T prob a)
type Expand prob a = a -> Space prob a



-- for ListUtils
-- | walk is a bounded version of the predefined function iterate
walk :: Int -> Trans.Change a -> Walk a
walk :: forall a. Int -> Change a -> Walk a
walk Int
n Change a
f = forall a. Int -> [a] -> [a]
take Int
n forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> a) -> a -> [a]
iterate Change a
f



-- * traces of random experiments

type RTrace a  = Rnd.T (Trace a)
type RWalk a   = a -> RTrace a

type RSpace prob a  = Rnd.T (Space prob a)
type RExpand prob a = a -> RSpace prob a


{- |
'merge' converts a list of 'RTrace's
into a list of randomized distributions, i.e., an 'RSpace',
by creating a randomized distribution for each list position across all traces
-}
merge :: (Fractional prob, Ord a) =>
   [RTrace a] -> RSpace prob a
merge :: forall prob a.
(Fractional prob, Ord a) =>
[RTrace a] -> RSpace prob a
merge =
   forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b. ([a] -> b) -> [[a]] -> [b]
zipListWith (forall prob a. (Num prob, Ord a) => T prob a -> T prob a
Dist.norm forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall prob a. Fractional prob => Spread prob a
Dist.uniform)) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence


-- for ListUtils
zipListWith :: ([a] -> b) -> [[a]] -> [b]
zipListWith :: forall a b. ([a] -> b) -> [[a]] -> [b]
zipListWith [a] -> b
f = forall a b. (a -> b) -> [a] -> [b]
map [a] -> b
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [[a]] -> [[a]]
transpose