{-# LANGUAGE Arrows              #-}
{-# LANGUAGE MultiWayIf          #-}
{-# LANGUAGE ScopedTypeVariables #-}
-- | QuickCheck generators for input streams.
--
-- Random stream generation can be customized usin three parameters:
--
-- - The distribution for the random time deltas ('Distribution').
-- - The maximum and minimum bounds for the time deltas ('Range').
-- - The maximum stream length ('Length').
--
-- The main function to generate streams is 'generateStream'. The specific
-- time deltas can be customized further using 'generateStreamWith'. Some
-- helper functions are provided to facilitate testing.

-- The function uniDistStreamMaxDT had the wrong type and the name on the
-- paper was: uniDistStream. This has been fixed.

module FRP.Yampa.QuickCheck
  (
    -- * Random stream generation
    generateStream
  , generateStreamWith

    -- ** Parameters used to generate random input streams
  , Distribution(..)
  , Range
  , Length

    -- ** Helpers for common cases
  , uniDistStream
  , uniDistStreamMaxDT
  , fixedDelayStream
  , fixedDelayStreamWith
  )
  where

import Control.Applicative ((<$>), pure)
import Data.Random.Normal
import FRP.Yampa
import Test.QuickCheck
import Test.QuickCheck.Gen

import FRP.Yampa.Stream

-- | Distributions used for time delta (DT) generation.
data Distribution = DistConstant                -- ^ Constant DT for the whole stream.
                  | DistNormal (DTime, DTime)   -- ^ Variable DT following normal distribution,
                                                --   with an average and a standard deviation.
                  | DistRandom                  -- ^ Completely random (positive) DT.

-- | Upper and lower bounds of time deltas for random DT generation.
type Range = (Maybe DTime, Maybe DTime)

-- | Optional maximum length for a stream, given as a time, or a number of
-- samples.
type Length = Maybe (Either Int DTime)


-- | Generate a random delta according to some required specifications.
generateDeltas :: Distribution -> Range -> Length -> Gen DTime
generateDeltas :: Distribution -> Range -> Length -> Gen DTime
generateDeltas Distribution
DistConstant            (Maybe DTime
mn, Maybe DTime
mx) Length
len = Maybe DTime -> Maybe DTime -> Gen DTime
generateDelta Maybe DTime
mn Maybe DTime
mx
generateDeltas Distribution
DistRandom              (Maybe DTime
mn, Maybe DTime
mx) Length
len = Maybe DTime -> Maybe DTime -> Gen DTime
generateDelta Maybe DTime
mn Maybe DTime
mx
generateDeltas (DistNormal (DTime
avg, DTime
dev)) (Maybe DTime
mn, Maybe DTime
mx) Length
len = DTime -> DTime -> Maybe DTime -> Maybe DTime -> Gen DTime
generateDSNormal DTime
avg DTime
dev Maybe DTime
mn Maybe DTime
mx

-- | Generate one random delta, possibly within a range.
generateDelta :: Maybe DTime -> Maybe DTime -> Gen DTime
generateDelta :: Maybe DTime -> Maybe DTime -> Gen DTime
generateDelta (Just DTime
x)  (Just DTime
y)  = (DTime, DTime) -> Gen DTime
forall a. Random a => (a, a) -> Gen a
choose (DTime
x, DTime
y)
generateDelta (Just DTime
x)  (Maybe DTime
Nothing) = (DTime
xDTime -> DTime -> DTime
forall a. Num a => a -> a -> a
+) (DTime -> DTime) -> Gen DTime -> Gen DTime
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen DTime
forall a. Arbitrary a => Gen a
arbitrary
generateDelta (Maybe DTime
Nothing) (Just DTime
y)  = (DTime, DTime) -> Gen DTime
forall a. Random a => (a, a) -> Gen a
choose (DTime
2.2251e-308, DTime
y)
generateDelta (Maybe DTime
Nothing) (Maybe DTime
Nothing) = Positive DTime -> DTime
forall a. Positive a -> a
getPositive (Positive DTime -> DTime) -> Gen (Positive DTime) -> Gen DTime
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen (Positive DTime)
forall a. Arbitrary a => Gen a
arbitrary

-- | Generate a random delta following a normal distribution,
--   and possibly within a given range.
generateDSNormal :: DTime -> DTime -> Maybe DTime -> Maybe DTime -> Gen DTime
generateDSNormal :: DTime -> DTime -> Maybe DTime -> Maybe DTime -> Gen DTime
generateDSNormal DTime
avg DTime
stddev Maybe DTime
m Maybe DTime
n = Gen DTime -> (DTime -> Bool) -> Gen DTime
forall a. Gen a -> (a -> Bool) -> Gen a
suchThat Gen DTime
gen (\DTime
x -> DTime -> Bool
mx DTime
x Bool -> Bool -> Bool
&& DTime -> Bool
mn DTime
x)
  where
    gen :: Gen DTime
gen = (QCGen -> Int -> DTime) -> Gen DTime
forall a. (QCGen -> Int -> a) -> Gen a
MkGen (\QCGen
r Int
_ -> let (DTime
x,QCGen
_) = (DTime, DTime) -> QCGen -> (DTime, QCGen)
forall g a.
(RandomGen g, Random a, Floating a) =>
(a, a) -> g -> (a, g)
normal' (DTime
avg, DTime
stddev) QCGen
r in DTime
x)
    mn :: DTime -> Bool
mn  = (DTime -> Bool)
-> (DTime -> DTime -> Bool) -> Maybe DTime -> DTime -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (\DTime
_ -> Bool
True) DTime -> DTime -> Bool
forall a. Ord a => a -> a -> Bool
(<=) Maybe DTime
m
    mx :: DTime -> Bool
mx  = (DTime -> Bool)
-> (DTime -> DTime -> Bool) -> Maybe DTime -> DTime -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (\DTime
_ -> Bool
True) DTime -> DTime -> Bool
forall a. Ord a => a -> a -> Bool
(>=) Maybe DTime
n

-- | Generate random samples up until a max time.
timeStampsUntil :: DTime -> Gen [DTime]
timeStampsUntil :: DTime -> Gen [DTime]
timeStampsUntil = Gen DTime -> DTime -> Gen [DTime]
timeStampsUntilWith Gen DTime
forall a. Arbitrary a => Gen a
arbitrary

-- | Generate random samples up until a max time, with a given time delta
--   generation function.
timeStampsUntilWith :: Gen DTime -> DTime -> Gen [DTime]
timeStampsUntilWith :: Gen DTime -> DTime -> Gen [DTime]
timeStampsUntilWith Gen DTime
arb DTime
ds = Gen DTime -> [DTime] -> DTime -> Gen [DTime]
timeStampsUntilWith' Gen DTime
arb [] DTime
ds
  where
    -- | Generate random samples up until a max time, with a given time delta
    --   generation function, and an initial suffix of time deltas.
    timeStampsUntilWith' :: Gen DTime -> [DTime] -> DTime -> Gen [DTime]
    timeStampsUntilWith' :: Gen DTime -> [DTime] -> DTime -> Gen [DTime]
timeStampsUntilWith' Gen DTime
arb [DTime]
acc DTime
ds
      | DTime
ds DTime -> DTime -> Bool
forall a. Ord a => a -> a -> Bool
< DTime
0    = [DTime] -> Gen [DTime]
forall (m :: * -> *) a. Monad m => a -> m a
return [DTime]
acc
      | Bool
otherwise = do DTime
d <- Gen DTime
arb
                       let acc' :: [DTime]
acc' = [DTime]
acc [DTime] -> [DTime] -> [DTime]
`seq` (DTime
dDTime -> [DTime] -> [DTime]
forall a. a -> [a] -> [a]
:[DTime]
acc)
                       [DTime]
acc' [DTime] -> Gen [DTime] -> Gen [DTime]
`seq` Gen DTime -> [DTime] -> DTime -> Gen [DTime]
timeStampsUntilWith' Gen DTime
arb [DTime]
acc' (DTime
ds DTime -> DTime -> DTime
forall a. Num a => a -> a -> a
- DTime
d)

-- | Generate random stream.
generateStream :: Arbitrary a
               => Distribution -> Range -> Length -> Gen (SignalSampleStream a)
generateStream :: Distribution -> Range -> Length -> Gen (SignalSampleStream a)
generateStream = (Int -> DTime -> Gen a)
-> Distribution -> Range -> Length -> Gen (SignalSampleStream a)
forall a.
Arbitrary a =>
(Int -> DTime -> Gen a)
-> Distribution -> Range -> Length -> Gen (SignalSampleStream a)
generateStreamWith (\Int
_ DTime
_ -> Gen a
forall a. Arbitrary a => Gen a
arbitrary)

-- | Generate random stream, parameterized by the value generator.
generateStreamWith :: Arbitrary a
                   => (Int -> DTime -> Gen a) -> Distribution -> Range -> Length -> Gen (SignalSampleStream a)
generateStreamWith :: (Int -> DTime -> Gen a)
-> Distribution -> Range -> Length -> Gen (SignalSampleStream a)
generateStreamWith Int -> DTime -> Gen a
arb Distribution
DistConstant Range
range  Length
len     = (Int -> DTime -> Gen a)
-> (DTime, Int) -> Gen (SignalSampleStream a)
forall a.
(Int -> DTime -> Gen a)
-> (DTime, Int) -> Gen (SignalSampleStream a)
generateConstantStream Int -> DTime -> Gen a
arb ((DTime, Int) -> Gen (SignalSampleStream a))
-> Gen (DTime, Int) -> Gen (SignalSampleStream a)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Range -> Length -> Gen (DTime, Int)
generateStreamLenDT Range
range Length
len
generateStreamWith Int -> DTime -> Gen a
arb Distribution
DistRandom   (Maybe DTime
m, Maybe DTime
n) Length
Nothing = do
  Int
l <- Gen Int
forall a. Arbitrary a => Gen a
arbitrary
  a
x <- Int -> DTime -> Gen a
arb Int
0 DTime
0
  [DTime]
ds <- Int -> (Int -> Gen DTime) -> Gen [DTime]
forall a. Int -> (Int -> Gen a) -> Gen [a]
vectorOfWith Int
l (\Int
_ -> Maybe DTime -> Maybe DTime -> Gen DTime
generateDelta Maybe DTime
m Maybe DTime
n)
  let f :: Int -> Gen a
f Int
n = Int -> DTime -> Gen a
arb Int
n ([DTime]
ds[DTime] -> Int -> DTime
forall a. [a] -> Int -> a
!!(Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1))
  [a]
xs <- Int -> (Int -> Gen a) -> Gen [a]
forall a. Int -> (Int -> Gen a) -> Gen [a]
vectorOfWith Int
l Int -> Gen a
f
  SignalSampleStream a -> Gen (SignalSampleStream a)
forall (m :: * -> *) a. Monad m => a -> m a
return (SignalSampleStream a -> Gen (SignalSampleStream a))
-> SignalSampleStream a -> Gen (SignalSampleStream a)
forall a b. (a -> b) -> a -> b
$ [a] -> [DTime] -> SignalSampleStream a
forall a. [a] -> [DTime] -> SignalSampleStream a
groupDeltas (a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
xs) [DTime]
ds

generateStreamWith Int -> DTime -> Gen a
arb Distribution
DistRandom (Maybe DTime
m, Maybe DTime
n) (Just (Left Int
l)) = do
  a
x <- Int -> DTime -> Gen a
arb Int
0 DTime
0
  [DTime]
ds <- Int -> (Int -> Gen DTime) -> Gen [DTime]
forall a. Int -> (Int -> Gen a) -> Gen [a]
vectorOfWith Int
l (\Int
_ -> Maybe DTime -> Maybe DTime -> Gen DTime
generateDelta Maybe DTime
m Maybe DTime
n)
  let f :: Int -> Gen a
f Int
n = Int -> DTime -> Gen a
arb Int
n ([DTime]
ds[DTime] -> Int -> DTime
forall a. [a] -> Int -> a
!!(Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1))
  [a]
xs <- Int -> (Int -> Gen a) -> Gen [a]
forall a. Int -> (Int -> Gen a) -> Gen [a]
vectorOfWith Int
l Int -> Gen a
f
  SignalSampleStream a -> Gen (SignalSampleStream a)
forall (m :: * -> *) a. Monad m => a -> m a
return (SignalSampleStream a -> Gen (SignalSampleStream a))
-> SignalSampleStream a -> Gen (SignalSampleStream a)
forall a b. (a -> b) -> a -> b
$ [a] -> [DTime] -> SignalSampleStream a
forall a. [a] -> [DTime] -> SignalSampleStream a
groupDeltas (a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
xs) [DTime]
ds

generateStreamWith Int -> DTime -> Gen a
arb Distribution
DistRandom (Maybe DTime
m, Maybe DTime
n) (Just (Right DTime
maxds)) = do
  [DTime]
ds <- Gen DTime -> DTime -> Gen [DTime]
timeStampsUntilWith (Maybe DTime -> Maybe DTime -> Gen DTime
generateDelta Maybe DTime
m Maybe DTime
n) DTime
maxds
  let l :: Int
l = [DTime] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [DTime]
ds
  a
x  <- Int -> DTime -> Gen a
arb Int
0 DTime
0
  let f :: Int -> Gen a
f Int
n = Int -> DTime -> Gen a
arb Int
n ([DTime]
ds[DTime] -> Int -> DTime
forall a. [a] -> Int -> a
!!(Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1))
  [a]
xs <- Int -> (Int -> Gen a) -> Gen [a]
forall a. Int -> (Int -> Gen a) -> Gen [a]
vectorOfWith Int
l Int -> Gen a
f
  SignalSampleStream a -> Gen (SignalSampleStream a)
forall (m :: * -> *) a. Monad m => a -> m a
return (SignalSampleStream a -> Gen (SignalSampleStream a))
-> SignalSampleStream a -> Gen (SignalSampleStream a)
forall a b. (a -> b) -> a -> b
$ [a] -> [DTime] -> SignalSampleStream a
forall a. [a] -> [DTime] -> SignalSampleStream a
groupDeltas (a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
xs) [DTime]
ds

generateStreamWith Int -> DTime -> Gen a
arb (DistNormal (DTime
avg, DTime
stddev)) (Maybe DTime
m, Maybe DTime
n) Length
Nothing = do
  Int
l <- Gen Int
forall a. Arbitrary a => Gen a
arbitrary
  a
x <- Int -> DTime -> Gen a
arb Int
0 DTime
0
  [DTime]
ds <- Int -> (Int -> Gen DTime) -> Gen [DTime]
forall a. Int -> (Int -> Gen a) -> Gen [a]
vectorOfWith Int
l (\Int
_ -> DTime -> DTime -> Maybe DTime -> Maybe DTime -> Gen DTime
generateDSNormal DTime
avg DTime
stddev Maybe DTime
m Maybe DTime
n)
  let f :: Int -> Gen a
f Int
n = Int -> DTime -> Gen a
arb Int
n ([DTime]
ds[DTime] -> Int -> DTime
forall a. [a] -> Int -> a
!!(Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1))
  [a]
xs <- Int -> (Int -> Gen a) -> Gen [a]
forall a. Int -> (Int -> Gen a) -> Gen [a]
vectorOfWith Int
l Int -> Gen a
f
  SignalSampleStream a -> Gen (SignalSampleStream a)
forall (m :: * -> *) a. Monad m => a -> m a
return (SignalSampleStream a -> Gen (SignalSampleStream a))
-> SignalSampleStream a -> Gen (SignalSampleStream a)
forall a b. (a -> b) -> a -> b
$ [a] -> [DTime] -> SignalSampleStream a
forall a. [a] -> [DTime] -> SignalSampleStream a
groupDeltas (a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
xs) [DTime]
ds

generateStreamWith Int -> DTime -> Gen a
arb (DistNormal (DTime
avg, DTime
stddev)) (Maybe DTime
m, Maybe DTime
n) (Just (Left Int
l)) = do
  a
x <- Int -> DTime -> Gen a
arb Int
0 DTime
0
  [DTime]
ds <- Int -> (Int -> Gen DTime) -> Gen [DTime]
forall a. Int -> (Int -> Gen a) -> Gen [a]
vectorOfWith Int
l (\Int
_ -> DTime -> DTime -> Maybe DTime -> Maybe DTime -> Gen DTime
generateDSNormal DTime
avg DTime
stddev Maybe DTime
m Maybe DTime
n)
  let f :: Int -> Gen a
f Int
n = Int -> DTime -> Gen a
arb Int
n ([DTime]
ds[DTime] -> Int -> DTime
forall a. [a] -> Int -> a
!!(Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1))
  [a]
xs <- Int -> (Int -> Gen a) -> Gen [a]
forall a. Int -> (Int -> Gen a) -> Gen [a]
vectorOfWith Int
l Int -> Gen a
f
  SignalSampleStream a -> Gen (SignalSampleStream a)
forall (m :: * -> *) a. Monad m => a -> m a
return (SignalSampleStream a -> Gen (SignalSampleStream a))
-> SignalSampleStream a -> Gen (SignalSampleStream a)
forall a b. (a -> b) -> a -> b
$ [a] -> [DTime] -> SignalSampleStream a
forall a. [a] -> [DTime] -> SignalSampleStream a
groupDeltas (a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
xs) [DTime]
ds

generateStreamWith Int -> DTime -> Gen a
arb (DistNormal (DTime
avg, DTime
stddev)) (Maybe DTime
m, Maybe DTime
n) (Just (Right DTime
maxds)) = do
  [DTime]
ds <- Gen DTime -> DTime -> Gen [DTime]
timeStampsUntilWith (DTime -> DTime -> Maybe DTime -> Maybe DTime -> Gen DTime
generateDSNormal DTime
avg DTime
stddev Maybe DTime
m Maybe DTime
n) DTime
maxds
  let l :: Int
l = [DTime] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [DTime]
ds
  a
x <- Int -> DTime -> Gen a
arb Int
0 DTime
0
  let f :: Int -> Gen a
f Int
n = Int -> DTime -> Gen a
arb Int
n ([DTime]
ds[DTime] -> Int -> DTime
forall a. [a] -> Int -> a
!!(Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1))
  [a]
xs <- Int -> (Int -> Gen a) -> Gen [a]
forall a. Int -> (Int -> Gen a) -> Gen [a]
vectorOfWith Int
l Int -> Gen a
f
  SignalSampleStream a -> Gen (SignalSampleStream a)
forall (m :: * -> *) a. Monad m => a -> m a
return (SignalSampleStream a -> Gen (SignalSampleStream a))
-> SignalSampleStream a -> Gen (SignalSampleStream a)
forall a b. (a -> b) -> a -> b
$ [a] -> [DTime] -> SignalSampleStream a
forall a. [a] -> [DTime] -> SignalSampleStream a
groupDeltas (a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
xs) [DTime]
ds

-- | Generate arbitrary stream with fixed length and constant delta.
generateConstantStream :: (Int -> DTime -> Gen a) -> (DTime, Int) -> Gen (SignalSampleStream a)
generateConstantStream :: (Int -> DTime -> Gen a)
-> (DTime, Int) -> Gen (SignalSampleStream a)
generateConstantStream Int -> DTime -> Gen a
arb (DTime
x, Int
length) = do
  [a]
ys <- Int -> (Int -> Gen a) -> Gen [a]
forall a. Int -> (Int -> Gen a) -> Gen [a]
vectorOfWith Int
length (\Int
n -> Int -> DTime -> Gen a
arb Int
n DTime
x)
  let ds :: [DTime]
ds = DTime -> [DTime]
forall a. a -> [a]
repeat DTime
x
  SignalSampleStream a -> Gen (SignalSampleStream a)
forall (m :: * -> *) a. Monad m => a -> m a
return (SignalSampleStream a -> Gen (SignalSampleStream a))
-> SignalSampleStream a -> Gen (SignalSampleStream a)
forall a b. (a -> b) -> a -> b
$ [a] -> [DTime] -> SignalSampleStream a
forall a. [a] -> [DTime] -> SignalSampleStream a
groupDeltas [a]
ys [DTime]
ds

-- | Generate arbitrary stream
generateStreamLenDT :: (Maybe DTime, Maybe DTime) -> Maybe (Either Int DTime) -> Gen (DTime, Int)
generateStreamLenDT :: Range -> Length -> Gen (DTime, Int)
generateStreamLenDT Range
range Length
len = do
  DTime
x <- (Maybe DTime -> Maybe DTime -> Gen DTime) -> Range -> Gen DTime
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Maybe DTime -> Maybe DTime -> Gen DTime
generateDelta Range
range
  Int
l <- case Length
len of
         Length
Nothing         -> ((Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+) (Int -> Int) -> (Positive Int -> Int) -> Positive Int -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Positive Int -> Int
forall a. Positive a -> a
getPositive) (Positive Int -> Int) -> Gen (Positive Int) -> Gen Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen (Positive Int)
forall a. Arbitrary a => Gen a
arbitrary
         Just (Left Int
l)   -> Int -> Gen Int
forall (f :: * -> *) a. Applicative f => a -> f a
pure Int
l
         Just (Right DTime
ds) -> (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1) (Int -> Int) -> Gen Int -> Gen Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Int -> Gen Int
forall (f :: * -> *) a. Applicative f => a -> f a
pure (DTime -> Int
forall a b. (RealFrac a, Integral b) => a -> b
floor (DTime
ds DTime -> DTime -> DTime
forall a. Fractional a => a -> a -> a
/ DTime
x)))
  (DTime, Int) -> Gen (DTime, Int)
forall (m :: * -> *) a. Monad m => a -> m a
return (DTime
x, Int
l)

-- generateStreamLenDT (Just x,  Just y)  (Just (Left l))   = (,) <$> choose (x, y)        <*> pure l
-- generateStreamLenDT (Just x,  Nothing) (Just (Left l))   = (,) <$> ((x+) <$> arbitrary) <*> pure l
-- generateStreamLenDT (Nothing, Just y)  (Just (Left l))   = (,) <$> choose (0, y)        <*> pure l
-- generateStreamLenDT (Just x,  _)       (Just (Right ts)) = (,) <$> pure x               <*> pure (floor (ts / x))
-- generateStreamLenDT (Just x,  _)       Nothing           = (,) <$> pure x               <*> arbitrary
-- generateStreamLenDT (Nothing, Nothing) Nothing           = (,) <$> arbitrary            <*> arbitrary
-- generateStreamLenDT (Nothing, Nothing) (Just (Left l))   = (,) <$> arbitrary            <*> pure l
-- generateStreamLenDT (Nothing, Nothing) (Just (Right ds)) = f2  <$> arbitrary
--   where
--     f2 l = (ds / fromIntegral l, l)


-- | Generate a stream of values with uniformly distributed time deltas.
uniDistStream :: Arbitrary a => Gen (SignalSampleStream a)
uniDistStream :: Gen (SignalSampleStream a)
uniDistStream = Distribution -> Range -> Length -> Gen (SignalSampleStream a)
forall a.
Arbitrary a =>
Distribution -> Range -> Length -> Gen (SignalSampleStream a)
generateStream Distribution
DistRandom (Maybe DTime
forall a. Maybe a
Nothing, Maybe DTime
forall a. Maybe a
Nothing) Length
forall a. Maybe a
Nothing

-- | Generate a stream of values with uniformly distributed time deltas, with a max DT.
uniDistStreamMaxDT :: Arbitrary a => DTime -> Gen (SignalSampleStream a)
uniDistStreamMaxDT :: DTime -> Gen (SignalSampleStream a)
uniDistStreamMaxDT DTime
maxDT = Distribution -> Range -> Length -> Gen (SignalSampleStream a)
forall a.
Arbitrary a =>
Distribution -> Range -> Length -> Gen (SignalSampleStream a)
generateStream Distribution
DistRandom (Maybe DTime
forall a. Maybe a
Nothing, DTime -> Maybe DTime
forall a. a -> Maybe a
Just DTime
maxDT ) Length
forall a. Maybe a
Nothing

-- | Generate a stream of values with a fixed time delta.
fixedDelayStream :: Arbitrary a => DTime -> Gen (SignalSampleStream a)
fixedDelayStream :: DTime -> Gen (SignalSampleStream a)
fixedDelayStream DTime
dt = Distribution -> Range -> Length -> Gen (SignalSampleStream a)
forall a.
Arbitrary a =>
Distribution -> Range -> Length -> Gen (SignalSampleStream a)
generateStream Distribution
DistConstant (DTime -> Maybe DTime
forall a. a -> Maybe a
Just DTime
dt, DTime -> Maybe DTime
forall a. a -> Maybe a
Just DTime
dt) Length
forall a. Maybe a
Nothing

-- | Generate a stream of values with a fixed time delta.
fixedDelayStreamWith :: Arbitrary a => (DTime -> a) ->  DTime -> Gen (SignalSampleStream a)
fixedDelayStreamWith :: (DTime -> a) -> DTime -> Gen (SignalSampleStream a)
fixedDelayStreamWith DTime -> a
f DTime
dt = (Int -> DTime -> Gen a)
-> Distribution -> Range -> Length -> Gen (SignalSampleStream a)
forall a.
Arbitrary a =>
(Int -> DTime -> Gen a)
-> Distribution -> Range -> Length -> Gen (SignalSampleStream a)
generateStreamWith Int -> DTime -> Gen a
forall (m :: * -> *) a. (Monad m, Integral a) => a -> DTime -> m a
f' Distribution
DistConstant (DTime -> Maybe DTime
forall a. a -> Maybe a
Just DTime
dt, DTime -> Maybe DTime
forall a. a -> Maybe a
Just DTime
dt) Length
forall a. Maybe a
Nothing
  where
    f' :: a -> DTime -> m a
f' a
n DTime
t = a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> m a) -> a -> m a
forall a b. (a -> b) -> a -> b
$ DTime -> a
f (a -> DTime
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
n DTime -> DTime -> DTime
forall a. Num a => a -> a -> a
* DTime
t)

-- * Extended quickcheck generator

-- | Generates a list of the given length.
vectorOfWith :: Int -> (Int -> Gen a) -> Gen [a]
vectorOfWith :: Int -> (Int -> Gen a) -> Gen [a]
vectorOfWith Int
k Int -> Gen a
genF = [Gen a] -> Gen [a]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [ Int -> Gen a
genF Int
i | Int
i <- [Int
1..Int
k] ]