module Data.Probability where

import Algebra

newtype ProbT t m a = ProbT (WriterT (Product t) (ListT m) a)
                    deriving (Unit,Functor,Applicative,Monad
                             ,MonadFix,MonadWriter (Product t))
type Prob t a = ProbT t Id a
                             
_ProbT :: Iso (ProbT t m a) (ProbT t' m' a') (WriterT (Product t) (ListT m) a) (WriterT (Product t') (ListT m') a')
_ProbT = iso ProbT (\(ProbT p) -> p)
probT :: (Functor m,Functor m') => Iso (ProbT t m a) (ProbT t' m' a') (m [(Product t,a)]) (m' [(Product t',a')])
probT = listT.writerT._ProbT
prob :: Iso (Prob t a) (Prob t' a') [(Product t,a)] [(Product t',a')]
prob = _Id.probT

instance (Monad m,Ring t,Fractional t) => MonadList (ProbT t m) where
  fork l = pure [(Product x,a) | a <- l]^.probT
    where x = 1/size l