```-- |
-- Module:     Control.Wire.Prefab.Noise
-- Copyright:  (c) 2012 Ertugrul Soeylemez
-- Maintainer: Ertugrul Soeylemez <es@ertes.de>
--
-- Various noise generators.

module Control.Wire.Prefab.Noise
( -- * Pure random noise
noise,
noiseR,
wackelkontakt,

-- * Effectful random noise
noiseM,
noiseRM,
wackelkontaktM
)
where

import Control.Wire.Classes
import Control.Wire.Prefab.Accum
import Control.Wire.Types
import Control.Wire.Wire
import Data.Monoid
import System.Random

-- | Pure noise generator.

noise ::
(Random b, RandomGen g)
=> g  -- ^ Initial random number generator.
-> Wire e m a b
noise = unfold (\g' _ -> random g')

-- | Noise generator.

noiseM ::
=> Wire e m a b
noiseM =
mkFixM \$ \_ _ -> liftM (Right \$!) getRandom

-- | Ranged noise generator.
--
-- * Depends: current instant.

noiseRM ::
=> Wire e m (b, b) b
noiseRM = mkFixM \$ \_ -> liftM (Right \$!) . getRandomR

-- | Pure ranged noise generator.
--
-- * Depends: current instant.

noiseR ::
(Random b, RandomGen g)
=> g  -- ^ Initial random number generator.
-> Wire e m (b, b) b
noiseR = unfold (\g' r -> randomR r g')

-- | Event:  Occurs randomly with the given probability.
--
-- * Inhibits: @wackelkontaktM p@ inhibits with probability @1 - p@.

wackelkontakt ::
(Monoid e, RandomGen g)
=> Double  -- ^ Occurrence probability.
-> g  -- ^ Initial random number generator.
-> Event e m a
wackelkontakt p g' =
mkPure \$ \_ x ->
let (e, g) = random g' in
(if (e < p) then Right x else Left mempty, wackelkontakt p g)

-- | Event:  Occurs randomly with the given probability.
--
-- * Inhibits: @wackelkontaktM p@ inhibits with probability @1 - p@.

wackelkontaktM ::