    -- |
    -- Module:     FRP.Netwire.Analyze
    -- Copyright:  (c) 2013 Ertugrul Soeylemez
    -- License:    BSD3
    -- Maintainer: Ertugrul Soeylemez <es@ertes.de>

    module FRP.Netwire.Analyze
        ( -- * Linear graphs
          lAvg,
          lGraph,
          lGraphN,

          -- * Staircase graphs
          sAvg,
          sGraph,
          sGraphN,

          -- * Peaks
          highPeak,
          highPeakBy,
          lowPeak,
          lowPeakBy,

          -- * Debug
          avgFps,
          framerate
        )
        where

    import Control.Wire
    import qualified Data.Foldable as F
    import qualified Data.Sequence as Seq
    import qualified FRP.Netwire.Utils.Timeline as Tl
    import Prelude hiding ((.), id)

    -- | Average framerate over the last given number of samples.  One
    -- important thing to note is that the value of this wire will generally
    -- disagree with 'sAvg' composed with 'framerate'.  This is expected,
    -- because this wire simply calculates the arithmetic mean, whereas
    -- 'sAvg' will actually integrate the framerate graph.
    --
    -- Note:  This wire is for debugging purposes only, because it exposes
    -- discrete time.  Do not taint your application with discrete time.
    --
    -- * Complexity: O(n) time and space wrt number of samples.

    avgFps ::
        (RealFloat b, HasTime t s)
        => Int  -- ^ Number of samples.
        -> Wire s e m a b
    avgFps :: forall b t s e (m :: * -> *) a.
    (RealFloat b, HasTime t s) =>
    Int -> Wire s e m a b
    avgFps Int
    int | Int
    int Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < Int
    1 = [Char] -> Wire s e m a b
    forall a. HasCallStack => [Char] -> a
    error [Char]
    "avgFps: Non-positive number of samples"
    avgFps Int
    int = Seq b -> Wire s e m a b
    forall {b} {s} {e} {m :: * -> *} {a}.
    HasTime b s =>
    Seq b -> Wire s e m a b
    loop Seq b
    forall a. Seq a
    Seq.empty
        where
        intf :: b
    intf = Int -> b
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    int
        afps :: Seq b -> b
    afps = (b -> b -> b
    forall a. Fractional a => a -> a -> a
    / b
    intf) (b -> b) -> (Seq b -> b) -> Seq b -> b
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . (b -> b -> b) -> b -> Seq b -> b
    forall b a. (b -> a -> b) -> b -> Seq a -> b
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    F.foldl' b -> b -> b
    forall a. Num a => a -> a -> a
    (+) b
    0

        loop :: Seq b -> Wire s e m a b
    loop Seq b
    ss' =
            (s -> a -> (b, Wire s e m a b)) -> Wire s e m a b
    forall s a b e (m :: * -> *).
    Monoid s =>
    (s -> a -> (b, Wire s e m a b)) -> Wire s e m a b
    mkSF ((s -> a -> (b, Wire s e m a b)) -> Wire s e m a b)
    -> (s -> a -> (b, Wire s e m a b)) -> Wire s e m a b
    forall a b. (a -> b) -> a -> b
    $ \s
    ds a
    _ ->
                let fps :: b
    fps = b -> b
    forall a. Fractional a => a -> a
    recip (b -> b) -> (s -> b) -> s -> b
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . b -> b
    forall a b. (Real a, Fractional b) => a -> b
    realToFrac (b -> b) -> (s -> b) -> s -> b
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . s -> b
    forall t s. HasTime t s => s -> t
    dtime (s -> b) -> s -> b
    forall a b. (a -> b) -> a -> b
    $ s
    ds
                    ss :: Seq b
    ss  = Int -> Seq b -> Seq b
    forall a. Int -> Seq a -> Seq a
    Seq.take Int
    int (b
    fps b -> Seq b -> Seq b
    forall a. a -> Seq a -> Seq a
    Seq.<| Seq b
    ss')
                in if b -> Bool
    forall a. RealFloat a => a -> Bool
    isInfinite b
    fps
                     then (Seq b -> b
    afps Seq b
    ss', Seq b -> Wire s e m a b
    loop Seq b
    ss')
                     else Seq b
    ss Seq b -> (b, Wire s e m a b) -> (b, Wire s e m a b)
    forall a b. a -> b -> b
    `seq` (Seq b -> b
    afps Seq b
    ss, Seq b -> Wire s e m a b
    loop Seq b
    ss)

    -- | Current framerate.
    --
    -- Note:  This wire is for debugging purposes only, because it exposes
    -- discrete time.  Do not taint your application with discrete time.
    --
    -- * Inhibits: when the clock stopped ticking.

    framerate ::
        (Eq b, Fractional b, HasTime t s, Monoid e)
        => Wire s e m a b
    framerate :: forall b t s e (m :: * -> *) a.
    (Eq b, Fractional b, HasTime t s, Monoid e) =>
    Wire s e m a b
    framerate =
        (s -> a -> (Either e b, Wire s e m a b)) -> Wire s e m a b
    forall s a e b (m :: * -> *).
    Monoid s =>
    (s -> a -> (Either e b, Wire s e m a b)) -> Wire s e m a b
    mkPure ((s -> a -> (Either e b, Wire s e m a b)) -> Wire s e m a b)
    -> (s -> a -> (Either e b, Wire s e m a b)) -> Wire s e m a b
    forall a b. (a -> b) -> a -> b
    $ \s
    ds a
    _ ->
            let dt :: b
    dt = t -> b
    forall a b. (Real a, Fractional b) => a -> b
    realToFrac (s -> t
    forall t s. HasTime t s => s -> t
    dtime s
    ds)
            in (if b
    dt b -> b -> Bool
    forall a. Eq a => a -> a -> Bool
    == b
    0 then e -> Either e b
    forall a b. a -> Either a b
    Left e
    forall a. Monoid a => a
    mempty else b -> Either e b
    forall a b. b -> Either a b
    Right (b -> b
    forall a. Fractional a => a -> a
    recip b
    dt), Wire s e m a b
    forall b t s e (m :: * -> *) a.
    (Eq b, Fractional b, HasTime t s, Monoid e) =>
    Wire s e m a b
    framerate)

    -- | High peak.
    --
    -- * Depends: now.

    highPeak :: (Ord a) => Wire s e m a a
    highPeak :: forall a s e (m :: * -> *). Ord a => Wire s e m a a
    highPeak = (a -> a -> Ordering) -> Wire s e m a a
    forall a s e (m :: * -> *). (a -> a -> Ordering) -> Wire s e m a a
    highPeakBy a -> a -> Ordering
    forall a. Ord a => a -> a -> Ordering
    compare

    -- | High peak with respect to the given comparison function.
    --
    -- * Depends: now.

    highPeakBy :: (a -> a -> Ordering) -> Wire s e m a a
    highPeakBy :: forall a s e (m :: * -> *). (a -> a -> Ordering) -> Wire s e m a a
    highPeakBy = Ordering -> (a -> a -> Ordering) -> Wire s e m a a
    forall o a s e (m :: * -> *).
    Eq o =>
    o -> (a -> a -> o) -> Wire s e m a a
    peakBy Ordering
    GT

    -- | Calculate the average of the signal over the given interval (from
    -- now).  This is done by calculating the integral of the corresponding
    -- linearly interpolated graph and dividing it by the interval length.
    -- See 'Tl.linAvg' for details.
    --
    -- Linear interpolation can be slow.  If you don't need it, you can use
    -- the staircase variant 'sAvg'.
    --
    -- Example: @lAvg 2@
    --
    -- * Complexity: O(s) space, O(s) time wrt number of samples in the
    --   interval.
    --
    -- * Depends: now.

    lAvg ::
        (Fractional a, Fractional t, HasTime t s)
        => t    -- ^ Interval size.
        -> Wire s e m a a
    lAvg :: forall a t s e (m :: * -> *).
    (Fractional a, Fractional t, HasTime t s) =>
    t -> Wire s e m a a
    lAvg t
    int =
        (s -> a -> (a, Wire s e m a a)) -> Wire s e m a a
    forall s a b e (m :: * -> *).
    Monoid s =>
    (s -> a -> (b, Wire s e m a b)) -> Wire s e m a b
    mkSF ((s -> a -> (a, Wire s e m a a)) -> Wire s e m a a)
    -> (s -> a -> (a, Wire s e m a a)) -> Wire s e m a a
    forall a b. (a -> b) -> a -> b
    $ \s
    ds a
    x ->
            let t :: t
    t = s -> t
    forall t s. HasTime t s => s -> t
    dtime s
    ds in
            (a
    x, t -> Timeline t a -> Wire s e m a a
    forall {s} {b} {e} {m :: * -> *}.
    (HasTime t s, Fractional b) =>
    t -> Timeline t b -> Wire s e m b b
    loop t
    t (t -> a -> Timeline t a
    forall t a. t -> a -> Timeline t a
    Tl.singleton t
    t a
    x))

        where
        loop :: t -> Timeline t b -> Wire s e m b b
    loop t
    t' Timeline t b
    tl' =
            (s -> b -> (b, Wire s e m b b)) -> Wire s e m b b
    forall s a b e (m :: * -> *).
    Monoid s =>
    (s -> a -> (b, Wire s e m a b)) -> Wire s e m a b
    mkSF ((s -> b -> (b, Wire s e m b b)) -> Wire s e m b b)
    -> (s -> b -> (b, Wire s e m b b)) -> Wire s e m b b
    forall a b. (a -> b) -> a -> b
    $ \s
    ds b
    x ->
                let t :: t
    t  = t
    t' t -> t -> t
    forall a. Num a => a -> a -> a
    + s -> t
    forall t s. HasTime t s => s -> t
    dtime s
    ds
                    t0 :: t
    t0 = t
    t t -> t -> t
    forall a. Num a => a -> a -> a
    - t
    int
                    tl :: Timeline t b
    tl = t -> Timeline t b -> Timeline t b
    forall a t.
    (Fractional a, Fractional t, Real t) =>
    t -> Timeline t a -> Timeline t a
    Tl.linCutL t
    t0 (t -> b -> Timeline t b -> Timeline t b
    forall t a. Ord t => t -> a -> Timeline t a -> Timeline t a
    Tl.insert t
    t b
    x Timeline t b
    tl')
                    a :: b
    a  = t -> t -> Timeline t b -> b
    forall a t.
    (Fractional a, Fractional t, Real t) =>
    t -> t -> Timeline t a -> a
    Tl.linAvg t
    t0 t
    t Timeline t b
    tl
                in (b
    a, t -> Timeline t b -> Wire s e m b b
    loop t
    t Timeline t b
    tl)

    -- | Produce a linearly interpolated graph for the given points in time,
    -- where the magnitudes of the points are distances from /now/.
    --
    -- Linear interpolation can be slow.  If you don't need it, you can use
    -- the faster staircase variant 'sGraph'.
    --
    -- Example: @lGraph [0, 1, 2]@ will output the interpolated inputs at
    -- /now/, one second before now and two seconds before now.
    --
    -- * Complexity: O(s) space, O(n * log s) time, where s = number of
    --   samples in the interval, n = number of requested data points.
    --
    -- * Depends: now.

    lGraph ::
        (Fractional a, Fractional t, HasTime t s)
        => [t]  -- ^ Data points to produce.
        -> Wire s e m a [a]
    lGraph :: forall a t s e (m :: * -> *).
    (Fractional a, Fractional t, HasTime t s) =>
    [t] -> Wire s e m a [a]
    lGraph [t]
    qts =
        (s -> a -> ([a], Wire s e m a [a])) -> Wire s e m a [a]
    forall s a b e (m :: * -> *).
    Monoid s =>
    (s -> a -> (b, Wire s e m a b)) -> Wire s e m a b
    mkSF ((s -> a -> ([a], Wire s e m a [a])) -> Wire s e m a [a])
    -> (s -> a -> ([a], Wire s e m a [a])) -> Wire s e m a [a]
    forall a b. (a -> b) -> a -> b
    $ \s
    ds a
    x ->
            let t :: t
    t = s -> t
    forall t s. HasTime t s => s -> t
    dtime s
    ds in
            (a
    x a -> [t] -> [a]
    forall a b. a -> [b] -> [a]
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
    <$ [t]
    qts, t -> Timeline t a -> Wire s e m a [a]
    forall {s} {a} {e} {m :: * -> *}.
    (HasTime t s, Fractional a) =>
    t -> Timeline t a -> Wire s e m a [a]
    loop t
    t (t -> a -> Timeline t a
    forall t a. t -> a -> Timeline t a
    Tl.singleton t
    t a
    x))

        where
        earliest :: t
    earliest = [t] -> t
    forall a. Ord a => [a] -> a
    forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
    maximum ((t -> t) -> [t] -> [t]
    forall a b. (a -> b) -> [a] -> [b]
    map t -> t
    forall a. Num a => a -> a
    abs [t]
    qts)

        loop :: t -> Timeline t a -> Wire s e m a [a]
    loop t
    t' Timeline t a
    tl' =
            (s -> a -> ([a], Wire s e m a [a])) -> Wire s e m a [a]
    forall s a b e (m :: * -> *).
    Monoid s =>
    (s -> a -> (b, Wire s e m a b)) -> Wire s e m a b
    mkSF ((s -> a -> ([a], Wire s e m a [a])) -> Wire s e m a [a])
    -> (s -> a -> ([a], Wire s e m a [a])) -> Wire s e m a [a]
    forall a b. (a -> b) -> a -> b
    $ \s
    ds a
    x ->
                let t :: t
    t  = t
    t' t -> t -> t
    forall a. Num a => a -> a -> a
    + s -> t
    forall t s. HasTime t s => s -> t
    dtime s
    ds
                    tl :: Timeline t a
    tl = t -> Timeline t a -> Timeline t a
    forall a t.
    (Fractional a, Fractional t, Real t) =>
    t -> Timeline t a -> Timeline t a
    Tl.linCutL (t
    t t -> t -> t
    forall a. Num a => a -> a -> a
    - t
    earliest) (t -> a -> Timeline t a -> Timeline t a
    forall t a. Ord t => t -> a -> Timeline t a -> Timeline t a
    Tl.insert t
    t a
    x Timeline t a
    tl')
                    ps :: [a]
    ps = (t -> a) -> [t] -> [a]
    forall a b. (a -> b) -> [a] -> [b]
    map (\t
    qt -> t -> Timeline t a -> a
    forall a t.
    (Fractional a, Fractional t, Real t) =>
    t -> Timeline t a -> a
    Tl.linLookup (t
    t t -> t -> t
    forall a. Num a => a -> a -> a
    - t -> t
    forall a. Num a => a -> a
    abs t
    qt) Timeline t a
    tl) [t]
    qts
                in ([a]
    ps, t -> Timeline t a -> Wire s e m a [a]
    loop t
    t Timeline t a
    tl)

    -- | Graph the given interval from now with the given number of evenly
    -- distributed points in time.  Convenience interface to 'lGraph'.
    --
    -- Linear interpolation can be slow.  If you don't need it, you can use
    -- the faster staircase variant 'sGraphN'.
    --
    -- * Complexity: O(s) space, O(n * log s) time, where s = number of
    --   samples in the interval, n = number of requested data points.
    --
    -- * Depends: now.

    lGraphN ::
        (Fractional a, Fractional t, HasTime t s)
        => t    -- ^ Interval to graph from now.
        -> Int  -- ^ Number of data points to produce.
        -> Wire s e m a [a]
    lGraphN :: forall a t s e (m :: * -> *).
    (Fractional a, Fractional t, HasTime t s) =>
    t -> Int -> Wire s e m a [a]
    lGraphN t
    int Int
    n
        | t
    int t -> t -> Bool
    forall a. Ord a => a -> a -> Bool
    <= t
    0 = [Char] -> Wire s e m a [a]
    forall a. HasCallStack => [Char] -> a
    error [Char]
    "lGraphN: Non-positive interval"
        | Int
    n Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Int
    0   = [Char] -> Wire s e m a [a]
    forall a. HasCallStack => [Char] -> a
    error [Char]
    "lGraphN: Non-positive number of data points"
    lGraphN t
    int Int
    n =
        let n1 :: Int
    n1   = Int
    n Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    1
            f :: a -> a
    f a
    qt = t -> a
    forall a b. (Real a, Fractional b) => a -> b
    realToFrac t
    int a -> a -> a
    forall a. Num a => a -> a -> a
    * a -> a
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral a
    qt a -> a -> a
    forall a. Fractional a => a -> a -> a
    / Int -> a
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    n1
        in [t] -> Wire s e m a [a]
    forall a t s e (m :: * -> *).
    (Fractional a, Fractional t, HasTime t s) =>
    [t] -> Wire s e m a [a]
    lGraph ((Int -> t) -> [Int] -> [t]
    forall a b. (a -> b) -> [a] -> [b]
    map Int -> t
    forall {a} {a}. (Fractional a, Integral a) => a -> a
    f [Int
    0..Int
    n1])

    -- | Low peak.
    --
    -- * Depends: now.

    lowPeak :: (Ord a) => Wire s e m a a
    lowPeak :: forall a s e (m :: * -> *). Ord a => Wire s e m a a
    lowPeak = (a -> a -> Ordering) -> Wire s e m a a
    forall a s e (m :: * -> *). (a -> a -> Ordering) -> Wire s e m a a
    lowPeakBy a -> a -> Ordering
    forall a. Ord a => a -> a -> Ordering
    compare

    -- | Low peak with respect to the given comparison function.
    --
    -- * Depends: now.

    lowPeakBy :: (a -> a -> Ordering) -> Wire s e m a a
    lowPeakBy :: forall a s e (m :: * -> *). (a -> a -> Ordering) -> Wire s e m a a
    lowPeakBy = Ordering -> (a -> a -> Ordering) -> Wire s e m a a
    forall o a s e (m :: * -> *).
    Eq o =>
    o -> (a -> a -> o) -> Wire s e m a a
    peakBy Ordering
    LT

    -- | Given peak with respect to the given comparison function.

    peakBy ::
        (Eq o)
        => o  -- ^ This ordering means the first argument is larger.
        -> (a -> a -> o)  -- ^ Compare two elements.
        -> Wire s e m a a
    peakBy :: forall o a s e (m :: * -> *).
    Eq o =>
    o -> (a -> a -> o) -> Wire s e m a a
    peakBy o
    o a -> a -> o
    comp = (a -> (a, Wire s e m a a)) -> Wire s e m a a
    forall a b s e (m :: * -> *).
    (a -> (b, Wire s e m a b)) -> Wire s e m a b
    mkSFN ((a -> (a, Wire s e m a a)) -> Wire s e m a a)
    -> (a -> (a, Wire s e m a a)) -> Wire s e m a a
    forall a b. (a -> b) -> a -> b
    $ \a
    x -> (a
    x, a -> Wire s e m a a
    forall {s} {e} {m :: * -> *}. a -> Wire s e m a a
    loop a
    x)
        where
        loop :: a -> Wire s e m a a
    loop a
    x' =
            (a -> (a, Wire s e m a a)) -> Wire s e m a a
    forall a b s e (m :: * -> *).
    (a -> (b, Wire s e m a b)) -> Wire s e m a b
    mkSFN ((a -> (a, Wire s e m a a)) -> Wire s e m a a)
    -> (a -> (a, Wire s e m a a)) -> Wire s e m a a
    forall a b. (a -> b) -> a -> b
    $ \a
    x ->
                a -> a
    forall a. a -> a
    forall {k} (cat :: k -> k -> *) (a :: k). Category cat => cat a a
    id (a -> a) -> (a -> Wire s e m a a) -> a -> (a, Wire s e m a a)
    forall b c c'. (b -> c) -> (b -> c') -> b -> (c, c')
    forall (a :: * -> * -> *) b c c'.
    Arrow a =>
    a b c -> a b c' -> a b (c, c')
    &&& a -> Wire s e m a a
    loop (a -> (a, Wire s e m a a)) -> a -> (a, Wire s e m a a)
    forall a b. (a -> b) -> a -> b
    $
                if a -> a -> o
    comp a
    x a
    x' o -> o -> Bool
    forall a. Eq a => a -> a -> Bool
    == o
    o then a
    x else a
    x'

    -- | Calculate the average of the signal over the given interval (from
    -- now).  This is done by calculating the integral of the corresponding
    -- staircase graph and dividing it by the interval length.  See
    -- 'Tl.scAvg' for details.
    --
    -- See also 'lAvg'.
    --
    -- Example: @sAvg 2@
    --
    -- * Complexity: O(s) space, O(s) time wrt number of samples in the
    --   interval.
    --
    -- * Depends: now.

    sAvg ::
        (Fractional a, Fractional t, HasTime t s)
        => t    -- ^ Interval size.
        -> Wire s e m a a
    sAvg :: forall a t s e (m :: * -> *).
    (Fractional a, Fractional t, HasTime t s) =>
    t -> Wire s e m a a
    sAvg t
    int =
        (s -> a -> (a, Wire s e m a a)) -> Wire s e m a a
    forall s a b e (m :: * -> *).
    Monoid s =>
    (s -> a -> (b, Wire s e m a b)) -> Wire s e m a b
    mkSF ((s -> a -> (a, Wire s e m a a)) -> Wire s e m a a)
    -> (s -> a -> (a, Wire s e m a a)) -> Wire s e m a a
    forall a b. (a -> b) -> a -> b
    $ \s
    ds a
    x ->
            let t :: t
    t = s -> t
    forall t s. HasTime t s => s -> t
    dtime s
    ds in
            (a
    x, t -> Timeline t a -> Wire s e m a a
    forall {s} {b} {e} {m :: * -> *}.
    (HasTime t s, Fractional b) =>
    t -> Timeline t b -> Wire s e m b b
    loop t
    t (t -> a -> Timeline t a
    forall t a. t -> a -> Timeline t a
    Tl.singleton t
    t a
    x))

        where
        loop :: t -> Timeline t b -> Wire s e m b b
    loop t
    t' Timeline t b
    tl' =
            (s -> b -> (b, Wire s e m b b)) -> Wire s e m b b
    forall s a b e (m :: * -> *).
    Monoid s =>
    (s -> a -> (b, Wire s e m a b)) -> Wire s e m a b
    mkSF ((s -> b -> (b, Wire s e m b b)) -> Wire s e m b b)
    -> (s -> b -> (b, Wire s e m b b)) -> Wire s e m b b
    forall a b. (a -> b) -> a -> b
    $ \s
    ds b
    x ->
                let t :: t
    t  = t
    t' t -> t -> t
    forall a. Num a => a -> a -> a
    + s -> t
    forall t s. HasTime t s => s -> t
    dtime s
    ds
                    t0 :: t
    t0 = t
    t t -> t -> t
    forall a. Num a => a -> a -> a
    - t
    int
                    tl :: Timeline t b
    tl = t -> Timeline t b -> Timeline t b
    forall t a. Ord t => t -> Timeline t a -> Timeline t a
    Tl.scCutL t
    t0 (t -> b -> Timeline t b -> Timeline t b
    forall t a. Ord t => t -> a -> Timeline t a -> Timeline t a
    Tl.insert t
    t b
    x Timeline t b
    tl')
                    a :: b
    a  = t -> t -> Timeline t b -> b
    forall a t. (Fractional a, Real t) => t -> t -> Timeline t a -> a
    Tl.scAvg t
    t0 t
    t Timeline t b
    tl
                in (b
    a, t -> Timeline t b -> Wire s e m b b
    loop t
    t Timeline t b
    tl)

    -- | Produce a staircase graph for the given points in time, where the
    -- magnitudes of the points are distances from /now/.
    --
    -- See also 'lGraph'.
    --
    -- Example: @sGraph [0, 1, 2]@ will output the inputs at /now/, one
    -- second before now and two seconds before now.
    --
    -- * Complexity: O(s) space, O(n * log s) time, where s = number of
    --   samples in the interval, n = number of requested data points.
    --
    -- * Depends: now.

    sGraph ::
        (Fractional t, HasTime t s)
        => [t]  -- ^ Data points to produce.
        -> Wire s e m a [a]
    sGraph :: forall t s e (m :: * -> *) a.
    (Fractional t, HasTime t s) =>
    [t] -> Wire s e m a [a]
    sGraph [t]
    qts =
        (s -> a -> ([a], Wire s e m a [a])) -> Wire s e m a [a]
    forall s a b e (m :: * -> *).
    Monoid s =>
    (s -> a -> (b, Wire s e m a b)) -> Wire s e m a b
    mkSF ((s -> a -> ([a], Wire s e m a [a])) -> Wire s e m a [a])
    -> (s -> a -> ([a], Wire s e m a [a])) -> Wire s e m a [a]
    forall a b. (a -> b) -> a -> b
    $ \s
    ds a
    x ->
            let t :: t
    t = s -> t
    forall t s. HasTime t s => s -> t
    dtime s
    ds in
            (a
    x a -> [t] -> [a]
    forall a b. a -> [b] -> [a]
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
    <$ [t]
    qts, t -> Timeline t a -> Wire s e m a [a]
    forall {s} {a} {e} {m :: * -> *}.
    HasTime t s =>
    t -> Timeline t a -> Wire s e m a [a]
    loop t
    t (t -> a -> Timeline t a
    forall t a. t -> a -> Timeline t a
    Tl.singleton t
    t a
    x))

        where
        earliest :: t
    earliest = [t] -> t
    forall a. Ord a => [a] -> a
    forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
    maximum ((t -> t) -> [t] -> [t]
    forall a b. (a -> b) -> [a] -> [b]
    map t -> t
    forall a. Num a => a -> a
    abs [t]
    qts)

        loop :: t -> Timeline t a -> Wire s e m a [a]
    loop t
    t' Timeline t a
    tl' =
            (s -> a -> ([a], Wire s e m a [a])) -> Wire s e m a [a]
    forall s a b e (m :: * -> *).
    Monoid s =>
    (s -> a -> (b, Wire s e m a b)) -> Wire s e m a b
    mkSF ((s -> a -> ([a], Wire s e m a [a])) -> Wire s e m a [a])
    -> (s -> a -> ([a], Wire s e m a [a])) -> Wire s e m a [a]
    forall a b. (a -> b) -> a -> b
    $ \s
    ds a
    x ->
                let t :: t
    t  = t
    t' t -> t -> t
    forall a. Num a => a -> a -> a
    + s -> t
    forall t s. HasTime t s => s -> t
    dtime s
    ds
                    tl :: Timeline t a
    tl = t -> Timeline t a -> Timeline t a
    forall t a. Ord t => t -> Timeline t a -> Timeline t a
    Tl.scCutL (t
    t t -> t -> t
    forall a. Num a => a -> a -> a
    - t
    earliest) (t -> a -> Timeline t a -> Timeline t a
    forall t a. Ord t => t -> a -> Timeline t a -> Timeline t a
    Tl.insert t
    t a
    x Timeline t a
    tl')
                    ps :: [a]
    ps = (t -> a) -> [t] -> [a]
    forall a b. (a -> b) -> [a] -> [b]
    map (\t
    qt -> t -> Timeline t a -> a
    forall t a. Ord t => t -> Timeline t a -> a
    Tl.scLookup (t
    t t -> t -> t
    forall a. Num a => a -> a -> a
    - t -> t
    forall a. Num a => a -> a
    abs t
    qt) Timeline t a
    tl) [t]
    qts
                in ([a]
    ps, t -> Timeline t a -> Wire s e m a [a]
    loop t
    t Timeline t a
    tl)

    -- | Graph the given interval from now with the given number of evenly
    -- distributed points in time.  Convenience interface to 'sGraph'.
    --
    -- See also 'lGraphN'.
    --
    -- * Complexity: O(s) space, O(n * log s) time, where s = number of
    --   samples in the interval, n = number of requested data points.
    --
    -- * Depends: now.

    sGraphN ::
        (Fractional t, HasTime t s)
        => t    -- ^ Interval to graph from now.
        -> Int  -- ^ Number of data points to produce.
        -> Wire s e m a [a]
    sGraphN :: forall t s e (m :: * -> *) a.
    (Fractional t, HasTime t s) =>
    t -> Int -> Wire s e m a [a]
    sGraphN t
    int Int
    n
        | t
    int t -> t -> Bool
    forall a. Ord a => a -> a -> Bool
    <= t
    0 = [Char] -> Wire s e m a [a]
    forall a. HasCallStack => [Char] -> a
    error [Char]
    "sGraphN: Non-positive interval"
        | Int
    n Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Int
    0   = [Char] -> Wire s e m a [a]
    forall a. HasCallStack => [Char] -> a
    error [Char]
    "sGraphN: Non-positive number of data points"
    sGraphN t
    int Int
    n =
        let n1 :: Int
    n1   = Int
    n Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    1
            f :: a -> a
    f a
    qt = t -> a
    forall a b. (Real a, Fractional b) => a -> b
    realToFrac t
    int a -> a -> a
    forall a. Num a => a -> a -> a
    * a -> a
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral a
    qt a -> a -> a
    forall a. Fractional a => a -> a -> a
    / Int -> a
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    n1
        in [t] -> Wire s e m a [a]
    forall t s e (m :: * -> *) a.
    (Fractional t, HasTime t s) =>
    [t] -> Wire s e m a [a]
    sGraph ((Int -> t) -> [Int] -> [t]
    forall a b. (a -> b) -> [a] -> [b]
    map Int -> t
    forall {a} {a}. (Fractional a, Integral a) => a -> a
    f [Int
    0..Int
    n1])