{-# LANGUAGE TypeOperators, ScopedTypeVariables
           , FlexibleInstances, MultiParamTypeClasses
           , GeneralizedNewtypeDeriving
 #-}
{-# OPTIONS_GHC -Wall -fno-warn-orphans #-}

-- For ghc-6.6 compatibility
-- {-# OPTIONS_GHC -fglasgow-exts -Wall #-}

----------------------------------------------------------------------
-- |
-- Module      :  FRP.Reactive.PrimReactive
-- Copyright   :  (c) Conal Elliott 2007
-- License     :  BSD3
-- 
-- Maintainer  :  conal@conal.net
-- Stability   :  experimental
-- 
-- Functional /events/ and /reactive values/.  Semantically, an 'Event' is
-- stream of future values in time order.  A 'Reactive' value is a
-- discretly time-varying value.
-- 
-- Many of the operations on events and reactive values are packaged as
-- instances of the standard type classes 'Monoid', 'Functor',
-- 'Applicative', and 'Monad'.
-- 
-- This module focuses on representation and primitives defined in terms
-- of the representation.  See also "FRP.Reactive.Reactive", which
-- re-exports this module, plus extras that do not exploit the
-- representation.  My intention for this separation is to ease
-- experimentation with alternative representations.
-- 
-- Although the basic 'Reactive' type describes /discretely/-changing
-- values, /continuously/-changing values can be modeled simply as
-- reactive functions.  See "FRP.Reactive.Behavior" for a convenient type
-- composition of 'Reactive' and a constant-optimized representation of
-- functions of time.  The exact packaging of discrete vs continuous will
-- probably change with more experience.
----------------------------------------------------------------------

module FRP.Reactive.PrimReactive
  ( -- * Events and reactive values
    EventG, ReactiveG
    -- * Operations on events and reactive values
  , stepper, switcher, withTimeGE, withTimeGR
  , futuresE, listEG, atTimesG, atTimeG
  , snapshotWith, accumE, accumR, once
  , withRestE, untilE
  -- , traceE, traceR
  -- , mkEvent, mkEventTrace, mkEventShow
  , eventOcc
    -- * To be moved elsewhere
  , joinMaybes, filterMP
  -- * To be removed when it gets used somewhere
  , isMonotoneR
  -- * Testing
  , batch, infE
  ) where

import Data.Monoid
import Control.Applicative
import Control.Monad
import Data.Function (on)

-- TODO: eliminate the needs for this stuff.
import Control.Concurrent (threadDelay)
import Control.Exception (evaluate)
import System.IO.Unsafe

import Test.QuickCheck hiding (evaluate)
import Test.QuickCheck.Instances
import Test.QuickCheck.Checkers
import Test.QuickCheck.Classes
-- import Data.List

-- TypeCompose
import Control.Compose ((:.)(..), inO2, Monoid_f(..))
import Data.Pair
import Control.Instances () -- Monoid (IO ())

import Data.Unamb (race)

import Data.Max
import Data.AddBounds
import FRP.Reactive.Future hiding (batch)
import FRP.Reactive.Internal.Reactive

{--------------------------------------------------------------------
    Events and reactive values
--------------------------------------------------------------------}

-- Bogus EqProp instance.  TODO: replace with a random equality test, such
-- that the collection of all generated tests covers equality.

instance (Eq a, Eq b, EqProp a, EqProp b) => EqProp (EventG a b) where
  a =-= b = foldr (.&.) (property True) $ zipWith (=-=) (f a) (f b)
    where
      f = take 20 . eFutures

arbitraryE :: (Num t, Ord t, Arbitrary t, Arbitrary u) => Gen (EventG t u)
arbitraryE = frequency 
  [ (1, liftA2 ((liftA. liftA) futuresE addStart) arbitrary futureList)
  , (4, liftA futuresE futureList)
  ]
  where
    earliestFuture = Future . (,) (Max MinBound)
    addStart = (:).earliestFuture
    futureList = frequency [(10, futureListFinite), (1,futureListInf)]
    futureListFinite = liftA2 (zipWith future) nondecreasing arbitrary
    futureListInf =
      liftA2 (zipWith future) (resize 10 nondecreasingInf)
                              (infiniteList arbitrary)

instance (Arbitrary t, Ord t, Num t, Arbitrary a) => Arbitrary (EventG t a) where
  arbitrary   = arbitraryE
  coarbitrary = coarbitrary . eFuture

----

-- Arbitrary works just like pairs:
instance (Arbitrary t, Arbitrary a, Num t, Ord t) => Arbitrary (ReactiveG t a) where
  arbitrary = liftA2 Stepper arbitrary arbitrary
  coarbitrary (a `Stepper` e) = coarbitrary e . coarbitrary a

instance Ord t => Model (ReactiveG t a) (t -> a) where
  model = rat

instance (Ord t, Arbitrary t, Show t, EqProp a) => EqProp (ReactiveG t a)
 where
   (=-=) = (=-=) `on` model

-- Initial value of a 'Reactive'
rInit :: ReactiveG t a -> a
rInit (a `Stepper` _) = a


{--------------------------------------------------------------------
    Instances
--------------------------------------------------------------------}

instance Ord t => Monoid (EventG t a) where
  mempty  = Event mempty
  mappend = inEvent2 merge

-- Standard instance for Applicative of Monoid
instance (Ord t, Monoid a) => Monoid (ReactiveG t a) where
  mempty  = pure mempty
  mappend = liftA2 mappend

-- | Merge two 'Future' streams into one.
merge :: Ord t => Binop (FutureG t (ReactiveG t a))
-- The following two lines seem to be too strict and are causing
-- reactive to lock up.  I.e. the time argument of one of these
-- must have been _|_, so when we pattern match against it, we 
-- block.
Future (Max MaxBound,_) `merge` v = v
u `merge` Future (Max MaxBound,_) = u
u `merge` v = 
  (inFutR (`merge` v) <$> u) `mappend` (inFutR (u `merge`) <$> v)

-- What's going on in this 'merge' definition?  Try two different
-- future paths.  If u arrives before v (or simultaneously), then
-- begin as u begins and then merge v with the rest of u.  Otherwise,
-- begin as v begins and then merge u with the rest of v.  Because of
-- the left-bias, make sure u fragments are always the first argument
-- to merge and v fragments are always the second.


-- Define functor instances in terms of each other.
instance Functor (EventG t) where
  fmap f = inEvent $ (fmap.fmap) f

instance Functor (ReactiveG t) where
  fmap f (a `Stepper` e) = f a `stepper` fmap f e

-- standard instance
instance Ord t => Applicative (EventG t) where
  pure = return
  _ <*> (Event (Future (Max MaxBound,_))) = mempty
  x <*> y = x `ap` y

-- standard instance
instance Ord t => Alternative (EventG t) where
  { empty = mempty; (<|>) = mappend }

instance Ord t => Pair (ReactiveG t) where
  -- pair :: ReactiveG t a -> ReactiveG t b -> ReactiveG t (a,b)
  (c `Stepper` ce) `pair` (d `Stepper` de) =
    (c,d) `accumR` pairEdit (ce,de)

instance Ord t => Applicative (ReactiveG t) where
  pure a = a `stepper` mempty
  -- Standard definition.  See 'Pair'.
  rf <*> rx = uncurry ($) <$> (rf `pair` rx)

-- A wonderful thing about the <*> definition for ReactiveG is that it
-- automatically caches the previous value of the function or argument
-- when the argument or function changes.


instance Ord t => Monad (EventG t) where
  return a = Event (pure (pure a))
  e >>= f  = joinE (fmap f e)

-- happy a t b. Same as (a `mappend` b) except takes advantage of knowledge
-- that t is a lower bound for the occurences of b. This allows for extra
-- laziness.
happy :: (Ord t) => EventG t a ->
                    Time t ->
                    EventG t a ->
                    EventG t a
happy a (Max MaxBound) _ = a
happy (Event (Future (Max MaxBound, _))) _ b = b
happy a@(Event (Future (t0, e `Stepper` ee'))) t b 
  | t0 <= t = (Event (Future (t0, e `Stepper` (happy ee' t b))))
  | otherwise = a `mappend` b


-- Note, joinE should not be called with an infinite list of events that all
-- occur at the same time.  It can't decide which occurs first.
joinE :: (Ord t) => EventG t (EventG t a) -> EventG t a
joinE (Event (Future (Max MaxBound, _))) = mempty
joinE (Event (Future (t0h, e `Stepper` ((Event (Future (Max MaxBound, _)))))))
  = adjustE t0h e
joinE (Event (Future (t0h, e `Stepper` ee'@((Event (Future (t1h, _)))))))
  = happy (adjustE t0h e) t1h (adjustTopE t0h (joinE ee'))

-- Original Version:
-- joinE (Event (Future (t0h, e `Stepper` ee'))) =
--   adjustE t0h e `mappend` adjustTopE t0h (joinE ee')

adjustTopE :: Ord t => Time t -> EventG t t1 -> EventG t t1
adjustTopE t0h (Event (Future (tah, r))) =
  Event (Future (t0h `max` tah,r))

adjustE :: Ord t => Time t -> EventG t t1 -> EventG t t1
adjustE _ e@(Event (Future (Max MaxBound, _))) = e

adjustE t0h (Event (Future (tah, a `Stepper` e))) =
  Event (Future (t1h,a `Stepper` adjustE t1h e))
  where
    t1h = t0h `max` tah

-- TODO: add adjustE explanation.  What's going on and why t1 in the
-- recursive call?  David's comment:
-- If we have an event [t1, t2] we know t2 >= t1 so (max t t2) == (max (max t t1) t2).
-- See http://hpaste.org/11518 for a def that doesn't change the lower bound.
-- 
-- What I remember is that this function is quite subtle w.r.t laziness.
-- There are some notes in the paper.  If i find instead that a simpler
-- definition is possible, so much the better.

-- Here's an alternative to joinE that is less strict, and doesn't cause
-- reactive to lock up.  Need to verify correctness.  (Does lock up with
-- the mappend optimization that eliminates a space/time leak.)
{-
joinE :: Ord t => EventG t (EventG t a) -> EventG t a
joinE (Event (Future (t0h, ~(e `Stepper` ee')))) =
   adjustE t0h (e `mappend` joinE ee')

adjustE t0h (Event (Future (tah, ~(a `Stepper` e)))) =
  Event (Future (t1h,a `Stepper` adjustE t1h e))
  where
    t1h = t0h `max` tah
-}

instance Ord t => MonadPlus (EventG t) where { mzero = mempty; mplus = mappend }

-- Standard instance for Applicative w/ join
instance Ord t => Monad (ReactiveG t) where
  return  = pure
  r >>= f = joinR (f <$> r)


{--------------------------------------------------------------------
    Operations on events and reactive values
--------------------------------------------------------------------}

-- | Reactive value from an initial value and a new-value event.
stepper :: a -> EventG t a -> ReactiveG t a
stepper = Stepper

-- -- | Turn a reactive value into an event, with the initial value
-- -- occurring at -Infinity.
-- --
-- -- Oops: breaks the semantic abstraction of 'Reactive' as a step
-- function.
-- rToE :: Ord t => ReactiveG t a -> EventG t a
-- rToE (a `Stepper` e) = pure a `mappend` e

-- | Switch between reactive values.
switcher :: Ord t => ReactiveG t a -> EventG t (ReactiveG t a) -> ReactiveG t a
r `switcher` e = join (r `stepper` e)

-- | Reactive 'join' (equivalent to 'join' but slightly more efficient, I think)
joinR :: Ord t => ReactiveG t (ReactiveG t a) -> ReactiveG t a

joinR ((a `Stepper` Event ur) `Stepper` e'@(Event urr)) = a `stepper` Event u
 where
   u = ((`switcher` e') <$> ur) `mappend` (join <$> urr)

-- The following simpler definition is wrong.  It keeps listening to @e@
-- even after @er@ has occurred.
-- joinR ((a `Stepper` e) `Stepper` er) = 
--   a `stepper` (e `mappend` join (rToE <$> er))

-- e  :: EventG t a
-- er :: EventG t (ReactiveG t a)
-- 
-- rToE <$> er ::: EventG t (EventG t a)
-- join (rToE <$> er) ::: EventG t a

-- | Access occurrence times in an event.  See also 'withTimeGR'.
withTimeGE :: EventG t a -> EventG t (a, Time t)
withTimeGE = inEvent $ inFuture $ \ (t,r) -> (t, withTimeGR t r)

-- | Access occurrence times in a reactive value.  See also 'withTimeGE'.
withTimeGR :: Time t -> ReactiveG t a -> ReactiveG t (a, Time t)
withTimeGR t (a `Stepper` e) = (a,t) `Stepper` withTimeGE e

-- | Convert a temporally monotonic list of futures to an event.  See also
-- the specialization 'listE'
listEG :: Ord t => [(t,a)] -> EventG t a
listEG = futuresE . map (uncurry future)

-- | Convert a temporally monotonic list of futures to an event
futuresE :: Ord t => [FutureG t a] -> EventG t a
futuresE [] = mempty
futuresE (Future (t,a) : futs) =
  -- trace ("l2E: "++show t) $
  Event (Future (t, a `stepper` futuresE futs))

-- TODO: redefine 'futuresE' as a fold
-- futuresE = foldr (\ fut e -> Event ((`stepper` e) <$> fut)) mempty

-- TODO: hide futuresE.  currently exported for use in TVal.  If I move to
-- Internal/Reactive, I have to move the monoid instance there, which
-- requires moving others as well.

-- | Event at given times.  See also 'atTimeG'.
atTimesG :: Ord t => [t] -> EventG t ()
atTimesG = listEG . fmap (flip (,) ())

-- | Single-occurrence event at given time.
atTimeG :: Ord t => t -> EventG t ()
atTimeG = atTimesG . pure

-- This variant of 'snapshot' has 'Nothing's where @b@ changed and @a@
-- didn't.
snap :: forall a b t. Ord t =>
        EventG t a -> ReactiveG t b -> EventG t (Maybe a, b)
ea `snap` (b0 `Stepper` eb) =
  (Nothing, b0) `accumE` (fmap fa ea `mappend` fmap fb eb)
 where
   fa :: a -> Unop (Maybe a, b)
   fb :: b -> Unop (Maybe a, b)
   fa a (_,b) = (Just a , b)
   fb b _     = (Nothing, b)

-- | Snapshot a reactive value whenever an event occurs and apply a
-- combining function to the event and reactive's values.
snapshotWith :: Ord t => (a -> b -> c) -> EventG t a -> ReactiveG t b -> EventG t c
snapshotWith f e r = joinMaybes $ fmap h (e `snap` r)
 where
   h (Nothing,_) = Nothing
   h (Just a ,b) = Just (f a b)

-- | Accumulating event, starting from an initial value and a
-- update-function event.  See also 'accumR'.
accumE :: a -> EventG t (a -> a) -> EventG t a
accumE a = inEvent $ fmap $ \ (f `Stepper` e') -> f a `accumR` e'

-- | Reactive value from an initial value and an updater event.  See also
-- 'accumE'.
accumR :: a -> EventG t (a -> a) -> ReactiveG t a
a `accumR` e = a `stepper` (a `accumE` e)

-- | Just the first occurrence of an event.
once :: Ord t => EventG t a -> EventG t a
once = inEvent $ fmap $ pure . rInit

-- | Extract a future representing the first occurrence of the event together
-- with the event of all occurrences after that one.
eventOcc :: (Ord t) => EventG t a -> FutureG t (a, EventG t a)
eventOcc (Event fut)  = (\ (Stepper a e) -> (a,e)) <$> fut


-- | Access the remainder with each event occurrence.
withRestE :: EventG t a -> EventG t (a, EventG t a)
withRestE = inEvent $ fmap $
	    \ (a `Stepper` e') -> (a,e') `stepper` withRestE e'


-- | Truncate first event at first occurrence of second event.
untilE :: Ord t => EventG t a -> EventG t b -> EventG t a
ea `untilE` Event (Future ~(tb,_)) = ea `untilET` tb

-- | Truncate first event at the given time.
untilET :: Ord t => EventG t a -> Time t -> EventG t a

-- Event (Future (ta, ~(a `Stepper` e'))) `untilET` t = 
--   if ta < t then
--     Event (Future (ta, a `Stepper` (e' `untilET` t)))
--   else
--     mempty

-- Hm.  I doubt that the definition above gives sufficient temporal
-- laziness.  No information can come out of the result until the value of
-- @ta < t@ is determined, which is usually at about time @ta `min` t@.

-- So, try the following definition instead.  It immediately provides
-- lower bounds of both @ta@ and @t@ as lower bounds of the constructed
-- event occurrences.

Event (Future ~(ta, a `Stepper` e')) `untilET` t = 
  Event (Future (ta', a `Stepper` (e' `untilET` t)))
 where
   ta' = (ta `min` t) `max` (if ta < t then ta else maxBound)

-- I'm not sure about @<@ vs @<=@ above.


-- | Sample a reactive value at a sequence of monotonically non-decreasing
-- times.  Deprecated, because it does not reveal when value is known to
-- be repeated in the output.  Those values won't be recomputed, but they
-- may be re-displayed.
rats :: Ord t => ReactiveG t a -> [t] -> [a] -- increasing times

_ `rats` [] = []

r@(a `Stepper` Event (Future (tr',r'))) `rats` ts@(t:ts')
  | ftime t <= tr' = a : r `rats` ts'
  | otherwise      = r' `rats` ts

-- Just for testing
rat :: Ord t => ReactiveG t a -> t -> a
rat r = head . rats r . (:[])


{--------------------------------------------------------------------
    Other instances
--------------------------------------------------------------------}

-- Standard instances
instance (Monoid_f f, Ord t) => Monoid_f (ReactiveG t :. f) where
    { mempty_f = O (pure mempty_f); mappend_f = inO2 (liftA2 mappend_f) }
instance (Ord t, Pair f) => Pair (ReactiveG t :. f) where pair = apPair

instance Unpair (ReactiveG t) where {pfst = fmap fst; psnd = fmap snd}

-- Standard instances
instance Ord t => Monoid_f (EventG t) where
  { mempty_f = mempty ; mappend_f = mappend }
instance Ord t => Monoid ((EventG t :. f) a) where
  { mempty = O mempty; mappend = inO2 mappend }
instance Ord t => Monoid_f (EventG t :. f) where
  { mempty_f = mempty ; mappend_f = mappend }
instance (Ord t, Copair f) => Pair (EventG t :. f) where
  pair = copair

-- Standard instance for functors
instance Unpair (EventG t) where {pfst = fmap fst; psnd = fmap snd}


{--------------------------------------------------------------------
    To be moved elsewhere
--------------------------------------------------------------------}

-- | Pass through @Just@ occurrences.
joinMaybes :: MonadPlus m => m (Maybe a) -> m a
joinMaybes = (>>= maybe mzero return)

-- | Pass through values satisfying @p@.
filterMP :: MonadPlus m => (a -> Bool) -> m a -> m a
filterMP p m = joinMaybes (liftM f m)
 where
   f a | p a        = Just a
       | otherwise  = Nothing

-- Alternatively:
-- filterMP p m = m >>= guarded p
--  where
--    guarded p x = guard (p x) >> return x

{--------------------------------------------------------------------
    Tests
--------------------------------------------------------------------}

-- TODO: Define more types like ApTy, use in batch below.  Move to checkers.
type ApTy f a b = f (a -> b) -> f a -> f b

batch :: TestBatch
batch = ( "Reactive.PrimReactive"
        , concatMap unbatch
          [ ("monotonicity",
              [ monotonicity2 "<*>"           
                 ((<*>) :: ApTy (EventG NumT) T T)
--                 ::    EventG NumT (T -> T)
--                    -> EventG NumT T
--                    -> EventG NumT T
              , monotonicity2 "adjustE"       (adjustE
                ::    Time NumT
                   -> EventG NumT NumT
                   -> EventG NumT NumT)
              , monotonicity  "join"          (join
                ::    EventG NumT (EventG NumT T)
                   -> EventG NumT T)
              , monotonicity  "withTimeGE"    (withTimeGE
                ::    EventG NumT T
                   -> EventG NumT (T, Time NumT))
              , monotonicity  "once"          (once
                ::    EventG NumT T
                   -> EventG NumT T)
              , monotonicity2 "accumE"        (accumE
                ::    T
                   -> EventG NumT (T -> T)
                   -> EventG NumT T)
              , monotonicity2 "mappend"       (mappend
                ::    EventG NumT T
                   -> EventG NumT T
                   -> EventG NumT T)
              , monotonicity2 "mplus"         (mplus
                ::    EventG NumT T
                   -> EventG NumT T
                   -> EventG NumT T)
              , monotonicity2 "<|>"           ((<|>)
                ::    EventG NumT T
                   -> EventG NumT T
                   -> EventG NumT T)
              , monotonicity2 "fmap"          (fmap
                ::    (T -> T)
                   -> EventG NumT T
                   -> EventG NumT T)
--              ,monotonicity2 "flip (>>=)"    (flip (>>=))
--              ,monotonicity2 (flip snapshot) "flip snapshot"
              ])
          , ("order preservation",
              [ simulEventOrder  "once"       (once
                ::    EventG NumT NumT
                   -> EventG NumT NumT)
              ])
          -- monad associativity fails
          -- , monad  (undefined :: EventG NumT (NumT,T,NumT))
          , monad  (undefined :: ReactiveG NumT (NumT,T,NumT))
          , monoid (undefined :: EventG NumT T)
          , monoid (undefined :: ReactiveG NumT [T])
--           , ("occurance count",
--              [("joinE", joinEOccuranceCount)]
--             )
          ]
        )

-- joinEOccuranceCount :: Property
-- joinEOccuranceCount =
--   forAll (finiteEvent $ finiteEvent arbitrary
--            :: Gen (EventG NumT (EventG NumT T)))
--          ((==) <$> (sum . map (length . toListE_) . toListE_)
--                <*> (length . toListE_ . joinE))

{-
toListE :: EventG t a -> [FutureG t a]
toListE (Event (Future (Max MaxBound, _             ))) = []
toListE (Event (Future (t0          , v `Stepper` e'))) = Future (t0,v) : toListE e'

toListE_ :: EventG t a -> [a]
toListE_ = map futVal . toListE
-}

monotonicity :: (Show a, Arbitrary a, Arbitrary t
                ,Num t, Ord t, Ord t')
             => String -> (EventG t a -> EventG t' a')
             -> (String,Property)
monotonicity n f = (n, property $ monotoneTest f)

monotonicity2 :: (Show a, Show b, Arbitrary a, Arbitrary b, Arbitrary t
                 ,Num t, Ord t, Ord t')
              => String -> (b -> EventG t a -> EventG t' a')
              -> (String,Property)
monotonicity2 n f = (n, property $ monotoneTest2 f)

monotoneTest :: (Ord t') => (EventG t a -> EventG t' a')
                         -> EventG t a
                         -> Bool
monotoneTest f e = unsafePerformIO (       (evaluate (isMonotoneE . f $ e))
                                    `race` slowTrue)

monotoneTest2 :: (Show a, Show b, Arbitrary a, Arbitrary b, Arbitrary t
                 ,Num t, Ord t, Ord t')
              => (b -> EventG t a -> EventG t' a')
              -> (b ,  EventG t a) -> Bool
monotoneTest2 f (x,e) =
  unsafePerformIO (       (evaluate (isMonotoneE (x `f` e)))
                   `race` slowTrue)

slowTrue :: IO Bool
slowTrue = do threadDelay 10
              return True

-- TODO: Replace this stuff with a use of delay from Data.Later in checkers.


isMonotoneE :: (Ord t) => EventG t a -> Bool
isMonotoneE = liftA2 (||) ((==(Max MaxBound)) . futTime . eFuture)
                          ((uncurry isMonotoneR') . unFuture . eFuture)

isMonotoneE' :: (Ord t) => (Time t) -> EventG t a -> Bool
isMonotoneE' t =
  liftA2 (||) ((==(Max MaxBound)) . futTime . eFuture)
              ((\(t',r) -> t <= t' && isMonotoneR' t' r) . unFuture . eFuture)

isMonotoneR :: (Ord t) => ReactiveG t a -> Bool
isMonotoneR (_ `Stepper` e) = isMonotoneE e

isMonotoneR' :: (Ord t) => (Time t) -> ReactiveG t a -> Bool
isMonotoneR' t (_ `Stepper` e) = isMonotoneE' t e

simulEventOrder :: (Arbitrary t, Num t, Ord t
                   ,Arbitrary t', Num t', Ord t'
                   ,Num t'', Ord t'', Num t''', Ord t''')
                => String -> (EventG t t' -> EventG t'' t''')
                -> (String, Property)
simulEventOrder n f =
  (n,forAll genEvent (isStillOrderedE . f))
  where
    genEvent :: (Arbitrary t1, Num t1, Ord t1, Arbitrary t2, Num t2, Ord t2)
             => Gen (EventG t1 t2)
    genEvent = liftA futuresE (liftA2 (zipWith future) nondecreasing
                                                          increasing)
    isStillOrderedE :: (Num t1, Ord t1, Num t2, Ord t2) => EventG t1 t2 -> Bool
    isStillOrderedE =
      liftA2 (||) ((==(Max MaxBound)) . futTime . eFuture)
                  (isStillOrderedR . futVal . eFuture)
    
    isStillOrderedR (a `Stepper` e) =
      isStillOrderedE' a e
    
    isStillOrderedE' a =
      liftA2 (||) ((==(Max MaxBound)) . futTime . eFuture)
                  (isStillOrderedR' a . futVal . eFuture)
    
    isStillOrderedR' a (b `Stepper` e) =
      a < b && isStillOrderedE' b e

-- An infinite event.  handy for testing.
infE :: EventG NumT NumT
infE = futuresE (zipWith future [1..] [1..])