-- | Monad helper functions
module Numeric.Probability.Monad where

import Control.Monad.HT ((<=<), )
import Control.Monad (liftM, )
import Prelude hiding (iterate, )

-- | composition of a list of monadic functions
compose :: Monad m => [a -> m a] -> a -> m a
compose :: forall (m :: * -> *) a. Monad m => [a -> m a] -> a -> m a
compose = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
(<=<)) forall (m :: * -> *) a. Monad m => a -> m a
return


iterate :: Monad m => Int -> (a -> m a) -> (a -> m a)
iterate :: forall (m :: * -> *) a. Monad m => Int -> (a -> m a) -> a -> m a
iterate Int
n a -> m a
f = forall (m :: * -> *) a. Monad m => [a -> m a] -> a -> m a
compose forall a b. (a -> b) -> a -> b
$ forall a. Int -> a -> [a]
replicate Int
n a -> m a
f


-- | like 'iterate' but returns all intermediate values
-- like Control.Monad.HT.iterateLimit, but counts differently.
-- Is it actually useful this way?
walk :: (Monad m) => Int -> (a -> m a) -> (a -> m [a])
walk :: forall (m :: * -> *) a. Monad m => Int -> (a -> m a) -> a -> m [a]
walk Int
n a -> m a
f =
   let recourse :: t -> a -> m [a]
recourse t
0 a
_ = forall (m :: * -> *) a. Monad m => a -> m a
return []
       recourse t
m a
x = forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (a
xforall a. a -> [a] -> [a]
:) (t -> a -> m [a]
recourse (forall a. Enum a => a -> a
pred t
m) forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< a -> m a
f a
x)
   in  forall {t}. (Eq t, Num t, Enum t) => t -> a -> m [a]
recourse Int
n


{- |
While loop with a posteriori check.
Loops at least once.
-}
doWhile :: Monad m => (a -> Bool) -> (a -> m a) -> (a -> m a)
doWhile :: forall (m :: * -> *) a.
Monad m =>
(a -> Bool) -> (a -> m a) -> a -> m a
doWhile a -> Bool
p a -> m a
t =
   let recourse :: a -> m a
recourse a
x = a -> m a
t a
x forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \a
l -> if a -> Bool
p a
l then a -> m a
recourse a
l else forall (m :: * -> *) a. Monad m => a -> m a
return a
l
   in  a -> m a
recourse

{- |
While loop with a priori check.
Can loop zero times.
-}
while :: Monad m => (a -> Bool) -> (a -> m a) -> (a -> m a)
while :: forall (m :: * -> *) a.
Monad m =>
(a -> Bool) -> (a -> m a) -> a -> m a
while a -> Bool
p a -> m a
t =
   let recourse :: a -> m a
recourse a
x = if a -> Bool
p a
x then a -> m a
t a
x forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= a -> m a
recourse else forall (m :: * -> *) a. Monad m => a -> m a
return a
x
   in  a -> m a
recourse


whileTrace :: Monad m => (a -> m Bool) -> m a -> m [a]
whileTrace :: forall (m :: * -> *) a. Monad m => (a -> m Bool) -> m a -> m [a]
whileTrace a -> m Bool
p m a
t =
   do a
x <- m a
t
      Bool
b <- a -> m Bool
p a
x
      forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (a
xforall a. a -> [a] -> [a]
:) forall a b. (a -> b) -> a -> b
$
         if Bool
b
           then forall (m :: * -> *) a. Monad m => (a -> m Bool) -> m a -> m [a]
whileTrace a -> m Bool
p m a
t
           else forall (m :: * -> *) a. Monad m => a -> m a
return []