content: -- |
  -- Module:     FRP.Netwire.Noise
  -- Copyright:  (c) 2013 Ertugrul Soeylemez
  -- License:    BSD3
  -- Maintainer: Ertugrul Soeylemez <es@ertes.de>
  
  module FRP.Netwire.Noise
      ( -- * Noise generators
        noise,
        noiseR,
        wackelkontakt,
  
        -- * Convenience
        stdNoise,
        stdNoiseR,
        stdWackelkontakt
      )
      where
  
  import Control.Wire
  import Prelude hiding ((.), id)
  import System.Random
  
  
  -- | Noise events with the given distance between events.  Use 'hold' or
  -- 'holdFor' to generate a staircase.
  
  noise ::
      (HasTime t s, Random b, RandomGen g)
      => t  -- ^ Time period.
      -> g  -- ^ Random number generator.
      -> Wire s e m a (Event b)
  noise int | int <= 0 = error "noise: Non-positive interval"
  noise int = periodicList int . randoms
  
  
  -- | Noise events with the given distance between events.  Noise will be
  -- in the given range.  Use 'hold' or 'holdFor' to generate a staircase.
  
  noiseR ::
      (HasTime t s, Random b, RandomGen g)
      => t       -- ^ Step duration.
      -> (b, b)  -- ^ Noise range.
      -> g       -- ^ Random number generator.
      -> Wire s e m a (Event b)
  noiseR int _ | int <= 0 = error "noiseR: Non-positive interval"
  noiseR int r = periodicList int . randomRs r
  
  
  -- | Convenience interface to 'noise' for 'StdGen'.
  
  stdNoise ::
      (HasTime t s, Random b)
      => t    -- ^ Step duration.
      -> Int  -- ^ 'StdGen' seed.
      -> Wire s e m a (Event b)
  stdNoise int = noise int . mkStdGen
  
  
  -- | Convenience interface to 'noiseR' for 'StdGen'.
  
  stdNoiseR ::
      (HasTime t s, Monad m, Random b)
      => t       -- ^ Step duration.
      -> (b, b)  -- ^ Noise range.
      -> Int     -- ^ 'StdGen' seed.
      -> Wire s e m a (Event b)
  stdNoiseR int r = noiseR int r . mkStdGen
  
  
  -- | Convenience interface to 'wackelkontakt' for 'StdGen'.
  
  stdWackelkontakt ::
      (HasTime t s, Monad m, Monoid e)
      => t    -- ^ Step duration.
      -> Double    -- ^ Probability to produce.
      -> Int  -- ^ 'StdGen' seed.
      -> Wire s e m a a
  stdWackelkontakt int p = wackelkontakt int p . mkStdGen
  
  
  -- | Randomly produce or inhibit with the given probability, each time
  -- for the given duration.
  --
  -- The name /Wackelkontakt/ (German for /slack joint/) is a Netwire
  -- running gag.  It makes sure that you revisit the documentation from
  -- time to time. =)
  --
  -- * Depends: now.
  
  wackelkontakt ::
      (HasTime t s, Monad m, Monoid e, RandomGen g)
      => t  -- ^ Duration.
      -> Double  -- ^ Probability to produce.
      -> g  -- ^ Random number generator.
      -> Wire s e m a a
  wackelkontakt int _ _ | int <= 0 = error "wackelkontakt: Non-positive duration"
  wackelkontakt int p g = fmap snd $ when (< p) . hold . noise int g &&& id
  