content: {-# LANGUAGE Arrows #-}
  {-# LANGUAGE CPP    #-}
  -- |
  -- Description : Test cases for signal functions working with events
  -- Copyright   : (c) Antony Courtney and Henrik Nilsson, Yale University, 2003-2004
  -- Authors     : Antony Courtney, Henrik Nilsson
  
  -- Notes pertaining to regression tests:
  -- - Add test cases for Yampa. There should be at least one test case for each
  --   "non-trivial" entity exported from Yampa.
  --
  -- - Make tests cases for after and repeatedly more robust.  Must not
  --   fail due to small discrepancies in floating point implementation.
  --
  --   01-May-2002:  evsrc_t7 currently fails in hugs.
  module Test.FRP.Yampa.EventS
      ( tests
      )
    where
  
  #if __GLASGOW_HASKELL__ < 710
  import Control.Applicative ((<*>))
  import Data.Functor        ((<$>))
  #endif
  import Test.QuickCheck hiding (once, sample)
  import Test.Tasty (TestTree, testGroup)
  import Test.Tasty.QuickCheck (testProperty)
  
  import FRP.Yampa as Yampa
  import FRP.Yampa.Stream
  import FRP.Yampa.QuickCheck
  import FRP.Yampa.LTLFuture
  
  import TestsCommon
  
  tests :: TestTree
  tests = testGroup "Regression tests for FRP.Yampa.EventS"
    [ testProperty "never (0, fixed)"         (property $ evsrc_t0 ~= evsrc_t0r)
    , testProperty "Events > No event"        prop_event_noevent
    , testProperty "eventS (1, fixed)"        (property $ evsrc_t1 ~= evsrc_t1r)
    , testProperty "Events > Now"             prop_event_now
    , testProperty "eventS (2, fixed)"        (property $ evsrc_t2 ~= evsrc_t2r)
    , testProperty "Events > After 0.0"       prop_event_after_0
    , testProperty "eventS (3, fixed)"        (property $ evsrc_t3 ~= evsrc_t3r)
    , testProperty "eventS (4, fixed)"        (property $ evsrc_t4 ~= evsrc_t4r)
    , testProperty "eventS (5, fixed)"        (property $ evsrc_t5 ~= evsrc_t5r)
    , testProperty "eventS (6, fixed)"        (property $ evsrc_t6 ~= evsrc_t6r)
    , testProperty "eventS (7, fixed)"        (property $ evsrc_t7 ~= evsrc_t7r)
    , testProperty "eventS (8, fixed)"        (property $ evsrc_t8 ~= evsrc_t8r)
    , testProperty "eventS (9, fixed)"        (property $ evsrc_t9 ~= evsrc_t9r)
    , testProperty "eventS (10, fixed)"       (property $ evsrc_t10 ~= evsrc_t10r)
    , testProperty "eventS (11, fixed)"       (property $ evsrc_t11 ~= evsrc_t11r)
    , testProperty "eventS (28, fixed)"       (property $ evsrc_t28 ~= evsrc_t28r)
    , testProperty "delayEvent (0, fixed)"    (property $ evsrc_t30 ~= evsrc_t30r)
    , testProperty "delayEvent (1, qc)"       propDelayEvent
    , testProperty "delayEventCat (0, fixed)" (property $ evsrc_t29 ~= evsrc_t29r)
    , testProperty "eventS (12, fixed)"       (property $ evsrc_t12 ~= evsrc_t12r)
    , testProperty "eventS (13, fixed)"       (property $ evsrc_t13 ~= evsrc_t13r)
    , testProperty "iEdge (0, qc)"            propIEdge
    , testProperty "edgeTag (0, qc)"          propEdgeTag
    , testProperty "edgeJust (0, qc)"         propEdgeJust
    , testProperty "eventS (14, fixed)"       (property $ evsrc_t14 ~= evsrc_t14r)
    , testProperty "eventS (15, fixed)"       (property $ evsrc_t15 ~= evsrc_t15r)
    , testProperty "eventS (16, fixed)"       (property $ evsrc_t16 ~= evsrc_t16r)
    , testProperty "notYet (0, qc)"           propNotYet
    , testProperty "eventS (17, fixed)"       (property $ evsrc_t17 ~= evsrc_t17r)
    , testProperty "eventS (18, fixed)"       (property $ evsrc_t18 ~= evsrc_t18r)
    , testProperty "eventS (19, fixed)"       (property $ evsrc_t19 ~= evsrc_t19r)
    , testProperty "eventS (20, fixed)"       (property $ evsrc_t20 ~= evsrc_t20r)
    , testProperty "eventS (21, fixed)"       (property $ evsrc_t21 ~= evsrc_t21r)
    , testProperty "eventS (22, fixed)"       (property $ evsrc_t22 ~= evsrc_t22r)
    , testProperty "eventS (23, fixed)"       (property $ evsrc_t23 ~= evsrc_t23r)
    , testProperty "eventS (24, fixed)"       (property $ evsrc_t24 ~= evsrc_t24r)
    , testProperty "eventS (25, fixed)"       (property $ evsrc_t25 ~= evsrc_t25r)
    , testProperty "eventS (26, fixed)"       (property $ evsrc_t26 ~= evsrc_t26r)
    , testProperty "eventS (27, fixed)"       (property $ evsrc_t27 ~= evsrc_t27r)
    , testProperty "snap (fixed)"             (property $ utils_t10 ~= utils_t10r)
    , testProperty "snapAfter (fixed)"        (property $ utils_t11 ~= utils_t11r)
    , testProperty "sample (fixed)"           (property $ utils_t12 ~= utils_t12r)
    , testProperty "sampleWindow (0, fixed)"  (property $ utils_t15 ~= utils_t15r)
    , testProperty "sampleWindow (1, fixed)"  (property $ utils_t16 ~= utils_t16r)
    , testProperty "after (0, fixed)"         (property $ utils_t13 ~= utils_t13r)
    , testProperty "after (1, fixed)"         (property $ utils_t14 ~= utils_t14r)
    ]
  
  -- * Basic event sources
  
  evsrc_t0 :: [Event ()]
  evsrc_t0 = testSF1 never
  
  evsrc_t0r =
    [ NoEvent, NoEvent, NoEvent, NoEvent  -- 0.0 s
    , NoEvent, NoEvent, NoEvent, NoEvent  -- 1.0 s
    , NoEvent, NoEvent, NoEvent, NoEvent  -- 2.0 s
    , NoEvent, NoEvent, NoEvent, NoEvent  -- 3.0 s
    , NoEvent, NoEvent, NoEvent, NoEvent  -- 4.0 s
    , NoEvent, NoEvent, NoEvent, NoEvent  -- 5.0 s
    , NoEvent
    ]
  
  prop_event_noevent =
      forAll myStream $ evalT $ Always $ prop (sfNever, const (== noEvent))
  
    where
      myStream :: Gen (SignalSampleStream Float)
      myStream = uniDistStream
      sfNever :: SF Float (Event Float)
      sfNever = never
  
  evsrc_t1 :: [Event Int]
  evsrc_t1 = testSF1 (now 42)
  
  evsrc_t1r :: [Event Int]
  evsrc_t1r =
    [ Event 42, NoEvent, NoEvent, NoEvent  -- 0.0 s
    , NoEvent,  NoEvent, NoEvent, NoEvent  -- 1.0 s
    , NoEvent,  NoEvent, NoEvent, NoEvent  -- 2.0 s
    , NoEvent,  NoEvent, NoEvent, NoEvent  -- 3.0 s
    , NoEvent,  NoEvent, NoEvent, NoEvent  -- 4.0 s
    , NoEvent,  NoEvent, NoEvent, NoEvent  -- 5.0 s
    , NoEvent
    ]
  
  prop_event_now =
      forAll myStream $ evalT $
        -- (sf, p0) /\ O [] (sf, pn)
        And (prop (sf, p0))                 -- Initially
            (Next $ Always $ prop (sf, pn)) -- After first sample
  
    where
      sf = Yampa.now 42.0
  
      p0 x y = y == Event 42.0
      pn x y = y == noEvent
  
      myStream :: Gen (SignalSampleStream Float)
      myStream = uniDistStream
  
  evsrc_t2 :: [Event Int]
  evsrc_t2 = testSF1 (after 0.0 42)
  evsrc_t2r :: [Event Int]
  evsrc_t2r =
    [ Event 42, NoEvent, NoEvent, NoEvent  -- 0.0 s
    , NoEvent,  NoEvent, NoEvent, NoEvent  -- 1.0 s
    , NoEvent,  NoEvent, NoEvent, NoEvent  -- 2.0 s
    , NoEvent,  NoEvent, NoEvent, NoEvent  -- 3.0 s
    , NoEvent,  NoEvent, NoEvent, NoEvent  -- 4.0 s
    , NoEvent,  NoEvent, NoEvent, NoEvent  -- 5.0 s
    , NoEvent
    ]
  
  prop_event_after_0 =
      forAll myStream $ evalT $
        -- (sf, p0) /\ O [] (sf, pn)
        And (prop (sf, p0))                 -- Initially
            (Next $ Always $ prop (sf, pn)) -- After first sample
  
    where
      sf = after 0.0 42.0
  
      p0 x y = y == Event 42.0
      pn x y = y == noEvent
  
      myStream :: Gen (SignalSampleStream Float)
      myStream = uniDistStream
  
  evsrc_t3 :: [Event Int]
  evsrc_t3 = testSF1 (after 3.0 42)
  
  evsrc_t3r :: [Event Int]
  evsrc_t3r =
    [ NoEvent,  NoEvent, NoEvent, NoEvent  -- 0.0 s
    , NoEvent,  NoEvent, NoEvent, NoEvent  -- 1.0 s
    , NoEvent,  NoEvent, NoEvent, NoEvent  -- 2.0 s
    , Event 42, NoEvent, NoEvent, NoEvent  -- 3.0 s
    , NoEvent,  NoEvent, NoEvent, NoEvent  -- 4.0 s
    , NoEvent,  NoEvent, NoEvent, NoEvent  -- 5.0 s
    , NoEvent
    ]
  
  evsrc_t4 :: [Event Int]
  evsrc_t4 = testSF1 (after 3.01 42)
  
  evsrc_t4r :: [Event Int]
  evsrc_t4r =
    [ NoEvent, NoEvent,  NoEvent, NoEvent  -- 0.0 s
    , NoEvent, NoEvent,  NoEvent, NoEvent  -- 1.0 s
    , NoEvent, NoEvent,  NoEvent, NoEvent  -- 2.0 s
    , NoEvent, Event 42, NoEvent, NoEvent  -- 3.0 s
    , NoEvent, NoEvent,  NoEvent, NoEvent  -- 4.0 s
    , NoEvent, NoEvent,  NoEvent, NoEvent  -- 5.0 s
    , NoEvent
    ]
  
  evsrc_t5 :: [Event Int]
  evsrc_t5 = testSF1 (repeatedly 0.795 42)
  
  evsrc_t5r :: [Event Int]
  evsrc_t5r =
    [ NoEvent,  NoEvent,  NoEvent,  NoEvent   -- 0.0 s
    , Event 42, NoEvent,  NoEvent,  Event 42  -- 1.0 s
    , NoEvent,  NoEvent,  Event 42, NoEvent   -- 2.0 s
    , NoEvent,  Event 42, NoEvent,  NoEvent   -- 3.0 s
    , Event 42, NoEvent,  NoEvent,  NoEvent   -- 4.0 s
    , Event 42, NoEvent,  NoEvent,  Event 42  -- 5.0 s
    , NoEvent
    ]
  
  evsrc_t6 :: [Event Int]
  evsrc_t6 = testSF1 (repeatedly 0.29999 42)
  
  evsrc_t6r :: [Event Int]
  evsrc_t6r =
    [ NoEvent,  NoEvent,  Event 42, Event 42  -- 0.0 s
    , Event 42, Event 42, Event 42, NoEvent   -- 1.0 s
    , Event 42, Event 42, Event 42, Event 42  -- 2.0 s
    , Event 42, NoEvent,  Event 42, Event 42  -- 3.0 s
    , Event 42, Event 42, Event 42, NoEvent   -- 4.0 s
    , Event 42, Event 42, Event 42, Event 42  -- 5.0 s
    , Event 42
    ]
  
  evsrc_t7 :: [Event Int]
  evsrc_t7 = testSF1 (repeatedly 0.24 42)
  
  evsrc_t7r :: [Event Int]
  evsrc_t7r =
    [ NoEvent,  Event 42, Event 42, Event 42  -- 0.0 s
    , Event 42, Event 42, Event 42, Event 42  -- 1.0 s
    , Event 42, Event 42, Event 42, Event 42  -- 2.0 s
    , Event 42, Event 42, Event 42, Event 42  -- 3.0 s
    , Event 42, Event 42, Event 42, Event 42  -- 4.0 s
    , Event 42, Event 42, Event 42, Event 42  -- 5.0 s
    , Event 42
    ]
  
  evsrc_t8 :: [Event Int]
  evsrc_t8 = testSF1 (afterEach [ (0.00, 1), (0.00, 2), (0.01, 3), (0.23, 4)
                                , (0.02, 5), (0.75, 6), (0.10, 7), (0.10, 8)
                                , (0.10, 9), (2.00, 10)
                                ]
                     )
  
  evsrc_t8r :: [Event Int]
  evsrc_t8r =
    [ Event 1,  Event 3,  Event 5,  NoEvent  -- 0.0 s
    , NoEvent,  Event 6,  Event 9,  NoEvent  -- 1.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 2.0 s
    , NoEvent,  NoEvent,  Event 10, NoEvent  -- 3.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 4.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 5.0 s
    , NoEvent
    ]
  
  evsrc_t9 :: [Event Int]
  evsrc_t9 = testSF1 (afterEach [ (2.03, 0)
                                , (0.00, 1), (0.00, 2), (0.01, 3), (0.23, 4)
                                , (0.02, 5), (0.75, 6), (0.10, 7), (0.10, 8)
                                , (0.10, 9), (2.00, 10), (0.00, 11), (0.00, 12)
                                ]
                     )
  
  evsrc_t9r :: [Event Int]
  evsrc_t9r =
    [ NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 0.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 1.0 s
    , NoEvent,  Event 0,  Event 4,  NoEvent  -- 2.0 s
    , NoEvent,  Event 6,  Event 9,  NoEvent  -- 3.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 4.0 s
    , NoEvent,  NoEvent,  Event 10, NoEvent  -- 5.0 s
    , NoEvent
    ]
  
  evsrc_t10 :: [Event [Int]]
  evsrc_t10 = testSF1 (afterEachCat [ (0.00, 1), (0.00, 2), (0.01, 3), (0.23, 4)
                                    , (0.02, 5), (0.75, 6), (0.10, 7), (0.10, 8)
                                    , (0.10, 9), (2.00, 10)
                                    ]
                      )
  
  evsrc_t10r :: [Event [Int]]
  evsrc_t10r =
    [ Event [1,2],  Event [3,4],    Event [5],  NoEvent  -- 0.0 s
    , NoEvent,      Event [6,7,8],  Event [9],  NoEvent  -- 1.0 s
    , NoEvent,      NoEvent,        NoEvent,    NoEvent  -- 2.0 s
    , NoEvent,      NoEvent,        Event [10], NoEvent  -- 3.0 s
    , NoEvent,      NoEvent,        NoEvent,    NoEvent  -- 4.0 s
    , NoEvent,      NoEvent,        NoEvent,    NoEvent  -- 5.0 s
    , NoEvent
    ]
  
  evsrc_t11 :: [Event [Int]]
  evsrc_t11 = testSF1 (afterEachCat [ (2.03, 0)
                                    , (0.00, 1), (0.00, 2), (0.01, 3), (0.23, 4)
                                    , (0.02, 5), (0.75, 6), (0.10, 7), (0.10, 8)
                                    , (0.10, 9), (2.00, 10)
                                    ]
                      )
  
  evsrc_t11r :: [Event [Int]]
  evsrc_t11r =
    [ NoEvent,  NoEvent,         NoEvent,     NoEvent  -- 0.0 s
    , NoEvent,  NoEvent,         NoEvent,     NoEvent  -- 1.0 s
    , NoEvent,  Event [0,1,2,3], Event [4,5], NoEvent  -- 2.0 s
    , NoEvent,  Event [6,7,8],   Event [9],   NoEvent  -- 3.0 s
    , NoEvent,  NoEvent,         NoEvent,     NoEvent  -- 4.0 s
    , NoEvent,  NoEvent,         Event [10],  NoEvent  -- 5.0 s
    , NoEvent
    ]
  
  propDelayEvent :: Property
  propDelayEvent =
      forAll delayFactorG $ \delayFactor ->
      forAll myStream $ evalT $
        Always $ SP $ (==) <$> originalSF delayFactor
                           <*> sfModelDelayEvent delayFactor
    where
      -- SF under test
      originalSF :: Int -> SF () (Event ())
      originalSF factor =
        time
          >>> arr cos
          >>> arr (< 0)
          >>> edge
          >>> delayEvent (fromIntegral factor * delay)
  
      -- Model SF that applies the delay internally
      sfModelDelayEvent :: Int -> SF () (Event ())
      sfModelDelayEvent factor =
        time
          >>> arr (\x -> x - (fromIntegral factor * delay))
          >>> arr cos
          >>> arr (< 0)
          >>> edge
  
      -- Generator: Factor by which the signal is delayed
      delayFactorG :: Gen Int
      delayFactorG = getPositive <$> arbitrary
  
      -- Generator: Random input stream. Delays and values are fixed but the
      -- length is not.
      myStream :: Gen (SignalSampleStream ())
      myStream = fixedDelayStream delay
  
      -- Constant: Max delay
      delay :: DTime
      delay = 0.01
  
  evsrc_t28 :: [(Event Int, Event Int)]
  evsrc_t28 = embed (repeatedly 0.5 ()
                     >>> accumBy (\n _ -> n + 1) 0
                     >>> identity &&& delayEvent 2.0)
                    (deltaEncode 0.125 (replicate 50 ()))
  
  evsrc_t28r =
    [ (NoEvent,NoEvent),  (NoEvent,NoEvent)  -- 0.0 s
    , (NoEvent,NoEvent),  (NoEvent,NoEvent)
    , (Event 1,NoEvent),  (NoEvent,NoEvent)  -- 0.5 s
    , (NoEvent,NoEvent),  (NoEvent,NoEvent)
    , (Event 2,NoEvent),  (NoEvent,NoEvent)  -- 1.0 s
    , (NoEvent,NoEvent),  (NoEvent,NoEvent)
    , (Event 3,NoEvent),  (NoEvent,NoEvent)  -- 1.5 s
    , (NoEvent,NoEvent),  (NoEvent,NoEvent)
    , (Event 4,NoEvent),  (NoEvent,NoEvent)  -- 2.0 s
    , (NoEvent,NoEvent),  (NoEvent,NoEvent)
    , (Event 5,Event 1),  (NoEvent,NoEvent)  -- 2.5 s
    , (NoEvent,NoEvent),  (NoEvent,NoEvent)
    , (Event 6,Event 2),  (NoEvent,NoEvent)  -- 3.0 s
    , (NoEvent,NoEvent),  (NoEvent,NoEvent)
    , (Event 7,Event 3),  (NoEvent,NoEvent)  -- 3.5 s
    , (NoEvent,NoEvent),  (NoEvent,NoEvent)
    , (Event 8,Event 4),  (NoEvent,NoEvent)  -- 4.0 s
    , (NoEvent,NoEvent),  (NoEvent,NoEvent)
    , (Event 9,Event 5),  (NoEvent,NoEvent)  -- 4.5 s
    , (NoEvent,NoEvent),  (NoEvent,NoEvent)
    , (Event 10,Event 6), (NoEvent,NoEvent)  -- 5.0 s
    , (NoEvent,NoEvent),  (NoEvent,NoEvent)
    , (Event 11,Event 7), (NoEvent,NoEvent)  -- 5.5 s
    , (NoEvent,NoEvent),  (NoEvent,NoEvent)
    , (Event 12,Event 8), (NoEvent,NoEvent)  -- 6.0 s
    ]
  
  -- "delayEvent" in a feedback loop. Should work like "repeatedly".
  evsrc_t30 :: [(Event ())]
  evsrc_t30 = embed (now ()
                     >>> (loop $
                            arr (uncurry lMerge)
                            >>> delayEvent 1.0
                            >>> arr dup))
                    (deltaEncode 0.125 (replicate 50 ()))
  
  evsrc_t30r :: [(Event ())]
  evsrc_t30r =
    [ NoEvent,  NoEvent, NoEvent, NoEvent  -- 0.0 s
    , NoEvent,  NoEvent, NoEvent, NoEvent  -- 0.5 s
    , Event (), NoEvent, NoEvent, NoEvent  -- 1.0 s
    , NoEvent,  NoEvent, NoEvent, NoEvent  -- 1.5 s
    , Event (), NoEvent, NoEvent, NoEvent  -- 2.0 s
    , NoEvent,  NoEvent, NoEvent, NoEvent  -- 2.5 s
    , Event (), NoEvent, NoEvent, NoEvent  -- 3.0 s
    , NoEvent,  NoEvent, NoEvent, NoEvent  -- 3.5 s
    , Event (), NoEvent, NoEvent, NoEvent  -- 4.0 s
    , NoEvent,  NoEvent, NoEvent, NoEvent  -- 4.5 s
    , Event (), NoEvent, NoEvent, NoEvent  -- 5.0 s
    , NoEvent,  NoEvent, NoEvent, NoEvent  -- 5.5 s
    , Event (), NoEvent                    -- 6.0 s
    ]
  
  evsrc_t29 :: [Event [Double]]
  evsrc_t29 = embed (time &&& repeatedly 0.5001 ()
                     >>> arr (\(t,e) -> e `tag` t)
                     >>> delayEventCat 3.0)
                    input
    where
      dts   = replicate 40 0.1 ++ [2.0] ++ replicate 40 0.1
      input = ((), [(dt, Just ()) | dt <- dts])
  
  {- Resulting input to the delay for reference:
  [ NoEvent,   NoEvent,   NoEvent, NoEvent, NoEvent  -- 0.0 s
  , NoEvent,   Event 0.6, NoEvent, NoEvent, NoEvent  -- 0.5 s
  , NoEvent,   Event 1.1, NoEvent, NoEvent, NoEvent  -- 1.0 s
  , NoEvent,   Event 1.6, NoEvent, NoEvent, NoEvent  -- 1.5 s
  , NoEvent,   Event 2.1, NoEvent, NoEvent, NoEvent  -- 2.0 s
  , NoEvent,   Event 2.6, NoEvent, NoEvent, NoEvent  -- 2.5 s
  , NoEvent,   Event 3.1, NoEvent, NoEvent, NoEvent  -- 3.0 s
  , NoEvent,   Event 3.6, NoEvent, NoEvent, NoEvent  -- 3.5 s
  , NoEvent                                          -- 4.0 s
  , Event 6.0, Event 6.1, NoEvent, NoEvent, NoEvent  -- 6.0 s
  , NoEvent,   Event 6.6, NoEvent, NoEvent, NoEvent  -- 6.5 s
  , NoEvent,   Event 7.1, NoEvent, NoEvent, NoEvent  -- 7.0 s
  , NoEvent,   Event 7.6, NoEvent, NoEvent, NoEvent  -- 7.5 s
  , NoEvent,   Event 8.1, NoEvent, NoEvent, NoEvent  -- 8.0 s
  , NoEvent,   Event 8.6, NoEvent, NoEvent, NoEvent  -- 8.5 s
  , NoEvent,   Event 9.1, NoEvent, NoEvent, NoEvent  -- 9.0 s
  , NoEvent,   Event 9.6, NoEvent, NoEvent, NoEvent  -- 9.5 s
  , NoEvent                                          -- 10.0 s
  ]
  -}
  
  evsrc_t29r =
    [ NoEvent, NoEvent,     NoEvent, NoEvent, NoEvent  -- 0.0 s
    , NoEvent, NoEvent,     NoEvent, NoEvent, NoEvent  -- 0.5 s
    , NoEvent, NoEvent,     NoEvent, NoEvent, NoEvent  -- 1.0 s
    , NoEvent, NoEvent,     NoEvent, NoEvent, NoEvent  -- 1.5 s
    , NoEvent, NoEvent,     NoEvent, NoEvent, NoEvent  -- 2.0 s
    , NoEvent, NoEvent,     NoEvent, NoEvent, NoEvent  -- 2.5 s
    , NoEvent, NoEvent,     NoEvent, NoEvent, NoEvent  -- 3.0 s
    , NoEvent, Event [0.6], NoEvent, NoEvent, NoEvent  -- 3.5 s
    , NoEvent                                          -- 4.0 s
    , Event [1.1, 1.6, 2.1, 2.6]                       -- 6.0 s
             , NoEvent,     Event [3.1], NoEvent, NoEvent
    , NoEvent, NoEvent,     Event [3.6], NoEvent, NoEvent  -- 6.5 s
    , NoEvent, NoEvent,     NoEvent,     NoEvent, NoEvent  -- 7.0 s
    , NoEvent, NoEvent,     NoEvent,     NoEvent, NoEvent  -- 7.5 s
    , NoEvent, NoEvent,     NoEvent,     NoEvent, NoEvent  -- 8.0 s
    , NoEvent, NoEvent,     NoEvent,     NoEvent, NoEvent  -- 8.5 s
    , NoEvent, Event [6.0], Event [6.1], NoEvent, NoEvent  -- 9.0 s
    , NoEvent, NoEvent,     Event [6.6], NoEvent, NoEvent  -- 9.5 s
    , NoEvent                                              -- 10.0 s
    ]
  
  evsrc_t12 :: [Event ()]
  evsrc_t12 = testSF1 (localTime >>> arr (>=0) >>> edge)
  
  evsrc_t12r =
    [ NoEvent, NoEvent, NoEvent, NoEvent  -- 0.0 s
    , NoEvent, NoEvent, NoEvent, NoEvent  -- 1.0 s
    , NoEvent, NoEvent, NoEvent, NoEvent  -- 2.0 s
    , NoEvent, NoEvent, NoEvent, NoEvent  -- 3.0 s
    , NoEvent, NoEvent, NoEvent, NoEvent  -- 4.0 s
    , NoEvent, NoEvent, NoEvent, NoEvent  -- 5.0 s
    , NoEvent
    ]
  
  evsrc_t13 :: [Event ()]
  evsrc_t13 = testSF1 (localTime >>> arr (>=4.26) >>> edge)
  
  evsrc_t13r =
    [ NoEvent, NoEvent, NoEvent,  NoEvent  -- 0.0 s
    , NoEvent, NoEvent, NoEvent,  NoEvent  -- 1.0 s
    , NoEvent, NoEvent, NoEvent,  NoEvent  -- 2.0 s
    , NoEvent, NoEvent, NoEvent,  NoEvent  -- 3.0 s
    , NoEvent, NoEvent, Event (), NoEvent  -- 4.0 s
    , NoEvent, NoEvent, NoEvent,  NoEvent  -- 5.0 s
    , NoEvent
    ]
  
  propIEdge :: Property
  propIEdge =
      forAll initialValG $ \initialVal ->
      forAll myStream $ evalT $
        Always $ SP $ (==) <$> originalSF initialVal <*> modelSF initialVal
    where
      -- SF under test
      originalSF :: Bool -> SF Bool (Event ())
      originalSF = iEdge
  
      -- Model SF that behaves like edge except for the initial sample
      modelSF :: Bool -> SF Bool (Event ())
      modelSF k = proc (x) -> do
        t <- time -< ()
        e <- edge -< x
  
        let result | t == 0 && not k && x = Event ()
                   | t == 0 && k          = NoEvent
                   | otherwise            = e
  
        returnA -< result
  
      -- Generator: Initialization value for iEdge
      initialValG :: Gen Bool
      initialValG = arbitrary
  
      -- Generator: Random input stream.
      myStream :: Gen (SignalSampleStream Bool)
      myStream = uniDistStream
  
  propEdgeTag :: Property
  propEdgeTag =
      forAll paramValG $ \paramVal ->
      forAll myStream $ evalT $
        Always $ SP $ (==) <$> originalSF paramVal <*> modelSF paramVal
    where
      -- SF under test
      originalSF :: Int -> SF Bool (Event Int)
      originalSF = edgeTag
  
      -- Model SF that tags the value in the event, after applying edge
      modelSF :: Int -> SF Bool (Event Int)
      modelSF k = edge >>^ arr (tagWith k)
  
      -- Generator: Tagging value
      paramValG :: Gen Int
      paramValG = arbitrary
  
      -- Generator: Random input stream.
      myStream :: Gen (SignalSampleStream Bool)
      myStream = uniDistStream
  
  propEdgeJust :: Property
  propEdgeJust =
      forAll myStream $ evalT $
        Always $ SP $ (==) <$> originalSF <*> modelSF
    where
      -- SF under test
      originalSF :: SF (Maybe Int) (Event Int)
      originalSF = edgeJust
  
      -- Model SF
      modelSF :: SF (Maybe Int) (Event Int)
      modelSF = loopPre (Just 0) $ arr $ \v@(n, _) ->
        case v of
          (Just x, Nothing) -> (Event x, n)
          _                 -> (NoEvent, n)
  
      -- Generator: Random input stream.
      myStream :: Gen (SignalSampleStream (Maybe Int))
      myStream = uniDistStream
  
  -- Raising edge detector.
  evsrc_isEdge False False = Nothing
  evsrc_isEdge False True  = Just ()
  evsrc_isEdge True  True  = Nothing
  evsrc_isEdge True  False = Nothing
  
  evsrc_t14 :: [Event ()]
  evsrc_t14 = testSF1 (localTime >>> arr (>=0) >>> edgeBy evsrc_isEdge False)
  
  evsrc_t14r =
    [ Event (), NoEvent, NoEvent, NoEvent  -- 0.0 s
    , NoEvent,  NoEvent, NoEvent, NoEvent  -- 1.0 s
    , NoEvent,  NoEvent, NoEvent, NoEvent  -- 2.0 s
    , NoEvent,  NoEvent, NoEvent, NoEvent  -- 3.0 s
    , NoEvent,  NoEvent, NoEvent, NoEvent  -- 4.0 s
    , NoEvent,  NoEvent, NoEvent, NoEvent  -- 5.0 s
    , NoEvent
    ]
  
  evsrc_t15 :: [Event ()]
  evsrc_t15 = testSF1 (localTime >>> arr (>=4.26) >>> edgeBy evsrc_isEdge False)
  
  evsrc_t15r =
    [ NoEvent, NoEvent, NoEvent,  NoEvent  -- 0.0 s
    , NoEvent, NoEvent, NoEvent,  NoEvent  -- 1.0 s
    , NoEvent, NoEvent, NoEvent,  NoEvent  -- 2.0 s
    , NoEvent, NoEvent, NoEvent,  NoEvent  -- 3.0 s
    , NoEvent, NoEvent, Event (), NoEvent  -- 4.0 s
    , NoEvent, NoEvent, NoEvent,  NoEvent  -- 5.0 s
    , NoEvent
    ]
  
  -- Raising and falling edge detector.
  evsrc_isEdge2 False False = Nothing
  evsrc_isEdge2 False True  = Just True
  evsrc_isEdge2 True  True  = Nothing
  evsrc_isEdge2 True  False = Just False
  
  evsrc_t16 :: [Event Bool]
  evsrc_t16 = testSF1 (localTime
                      >>> arr (\t -> t >=2.01 && t <= 4.51)
                      >>> edgeBy evsrc_isEdge2 True)
  
  evsrc_t16r =
    [ Event False, NoEvent,    NoEvent, NoEvent      -- 0.0 s
    , NoEvent,     NoEvent,    NoEvent, NoEvent      -- 1.0 s
    , NoEvent,     Event True, NoEvent, NoEvent      -- 2.0 s
    , NoEvent,     NoEvent,    NoEvent, NoEvent      -- 3.0 s
    , NoEvent,     NoEvent,    NoEvent, Event False  -- 4.0 s
    , NoEvent,     NoEvent,    NoEvent, NoEvent      -- 5.0 s
    , NoEvent
    ]
  
  -- * Stateful event suppression
  
  propNotYet :: Property
  propNotYet =
      forAll myStream $ evalT $
        Always $ SP $ (==) <$> originalSF
                           <*> modelSF
    where
      -- SF under test
      originalSF :: SF (Event Int) (Event Int)
      originalSF = notYet
  
      -- Model SF that sets the initial value of an Event signal to noEvent
      modelSF :: SF (Event Int) (Event Int)
      modelSF = const noEvent -=> identity
  
      -- Generator: Random input stream.
      myStream :: Gen (SignalSampleStream (Event Int))
      myStream = uniDistStream
  
  evsrc_t17 :: [Event Int]
  evsrc_t17 = testSF1 (now 17 &&& repeatedly 0.795 42
                       >>> arr (uncurry merge)
                       >>> notYet)
  
  evsrc_t17r :: [Event Int]
  evsrc_t17r =
    [ NoEvent,  NoEvent,  NoEvent,  NoEvent   -- 0.0 s
    , Event 42, NoEvent,  NoEvent,  Event 42  -- 1.0 s
    , NoEvent,  NoEvent,  Event 42, NoEvent   -- 2.0 s
    , NoEvent,  Event 42, NoEvent,  NoEvent   -- 3.0 s
    , Event 42, NoEvent,  NoEvent,  NoEvent   -- 4.0 s
    , Event 42, NoEvent,  NoEvent,  Event 42  -- 5.0 s
    , NoEvent
    ]
  
  evsrc_t18 :: [Event Int]
  evsrc_t18 = testSF1 (now 42 >>> once)
  
  evsrc_t18r :: [Event Int]
  evsrc_t18r =
    [ Event 42, NoEvent,  NoEvent,  NoEvent  -- 0.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 1.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 2.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 3.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 4.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 5.0 s
    , NoEvent
    ]
  
  evsrc_t19 :: [Event Int]
  evsrc_t19 = testSF1 (repeatedly 0.8 42 >>> once)
  
  evsrc_t19r :: [Event Int]
  evsrc_t19r =
    [ NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 0.0 s
    , Event 42, NoEvent,  NoEvent,  NoEvent  -- 1.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 2.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 3.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 4.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 5.0 s
    , NoEvent
    ]
  
  evsrc_t20 :: [Event Int]
  evsrc_t20 = testSF1 (now 42 >>> takeEvents 0)
  
  evsrc_t20r :: [Event Int]
  evsrc_t20r =
    [ NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 0.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 1.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 2.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 3.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 4.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 5.0 s
    , NoEvent
    ]
  
  evsrc_t21 :: [Event Int]
  evsrc_t21 = testSF1 (now 42 >>> takeEvents 1)
  
  evsrc_t21r :: [Event Int]
  evsrc_t21r =
    [ Event 42, NoEvent,  NoEvent,  NoEvent  -- 0.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 1.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 2.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 3.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 4.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 5.0 s
    , NoEvent
    ]
  
  evsrc_t22 :: [Event Int]
  evsrc_t22 = testSF1 (repeatedly 0.8 42 >>> takeEvents 4)
  
  evsrc_t22r :: [Event Int]
  evsrc_t22r =
    [ NoEvent,  NoEvent,  NoEvent,  NoEvent   -- 0.0 s
    , Event 42, NoEvent,  NoEvent,  Event 42  -- 1.0 s
    , NoEvent,  NoEvent,  Event 42, NoEvent   -- 2.0 s
    , NoEvent,  Event 42, NoEvent,  NoEvent   -- 3.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent   -- 4.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent   -- 5.0 s
    , NoEvent
    ]
  
  evsrc_t23 :: [Event Int]
  evsrc_t23 = testSF1 (repeatedly 0.2 42 >>> takeEvents 4)
  
  evsrc_t23r :: [Event Int]
  evsrc_t23r =
    [ NoEvent,  Event 42, Event 42, Event 42  -- 0.0 s
    , Event 42, NoEvent,  NoEvent,  NoEvent   -- 1.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent   -- 2.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent   -- 3.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent   -- 4.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent   -- 5.0 s
    , NoEvent
    ]
  
  evsrc_t24 :: [Event Int]
  evsrc_t24 = testSF1 (now 42 >>> dropEvents 0)
  
  evsrc_t24r :: [Event Int]
  evsrc_t24r =
    [ Event 42, NoEvent,  NoEvent,  NoEvent  -- 0.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 1.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 2.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 3.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 4.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 5.0 s
    , NoEvent
    ]
  
  evsrc_t25 :: [Event Int]
  evsrc_t25 = testSF1 (now 42 >>> dropEvents 1)
  
  evsrc_t25r :: [Event Int]
  evsrc_t25r =
    [ NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 0.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 1.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 2.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 3.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 4.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent  -- 5.0 s
    , NoEvent
    ]
  
  evsrc_t26 :: [Event Int]
  -- Drop 5 events to get rid of the event at 4.0 s which may or may not happen
  -- exactly there.
  evsrc_t26 = testSF1 (repeatedly 0.8 42 >>> dropEvents 5)
  
  evsrc_t26r :: [Event Int]
  evsrc_t26r =
    [ NoEvent,  NoEvent,  NoEvent,  NoEvent   -- 0.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent   -- 1.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent   -- 2.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent   -- 3.0 s
    , NoEvent,  NoEvent,  NoEvent,  NoEvent   -- 4.0 s
    , Event 42, NoEvent,  NoEvent,  Event 42  -- 5.0 s
    , NoEvent
    ]
  
  evsrc_t27 :: [Event Int]
  evsrc_t27 = testSF1 (repeatedly 0.2 42 >>> dropEvents 4)
  
  evsrc_t27r :: [Event Int]
  evsrc_t27r =
    [ NoEvent,  NoEvent,  NoEvent,  NoEvent   -- 0.0 s
    , NoEvent,  Event 42, Event 42, Event 42  -- 1.0 s
    , Event 42, Event 42, Event 42, Event 42  -- 2.0 s
    , Event 42, Event 42, Event 42, Event 42  -- 3.0 s
    , Event 42, Event 42, Event 42, Event 42  -- 4.0 s
    , Event 42, Event 42, Event 42, Event 42  -- 5.0 s
    , Event 42
    ]
  
  -- ** Hybrid continuous-to-discrete SF combinators.
  
  utils_t10 :: [Event Double]
  utils_t10 = testSF1 snap
  
  utils_t10r =
    [ Event 0.0, NoEvent, NoEvent, NoEvent  -- 0.0 s
    , NoEvent,   NoEvent, NoEvent, NoEvent  -- 1.0 s
    , NoEvent,   NoEvent, NoEvent, NoEvent  -- 2.0 s
    , NoEvent,   NoEvent, NoEvent, NoEvent  -- 3.0 s
    , NoEvent,   NoEvent, NoEvent, NoEvent  -- 4.0 s
    , NoEvent,   NoEvent, NoEvent, NoEvent  -- 5.0 s
    , NoEvent
    ]
  
  utils_t11 :: [Event Double]
  utils_t11 = testSF1 (snapAfter 2.6)
  
  utils_t11r =
    [ NoEvent, NoEvent, NoEvent, NoEvent     -- 0.0 s
    , NoEvent, NoEvent, NoEvent, NoEvent     -- 1.0 s
    , NoEvent, NoEvent, NoEvent, Event 11.0  -- 2.0 s
    , NoEvent, NoEvent, NoEvent, NoEvent     -- 3.0 s
    , NoEvent, NoEvent, NoEvent, NoEvent     -- 4.0 s
    , NoEvent, NoEvent, NoEvent, NoEvent     -- 5.0 s
    , NoEvent
    ]
  
  utils_t12 :: [Event Double]
  utils_t12 = testSF1 (sample 0.99)
  
  utils_t12r =
    [ NoEvent,    NoEvent, NoEvent, NoEvent  -- 0.0 s
    , Event 4.0,  NoEvent, NoEvent, NoEvent  -- 1.0 s
    , Event 8.0,  NoEvent, NoEvent, NoEvent  -- 2.0 s
    , Event 12.0, NoEvent, NoEvent, NoEvent  -- 3.0 s
    , Event 16.0, NoEvent, NoEvent, NoEvent  -- 4.0 s
    , Event 20.0, NoEvent, NoEvent, NoEvent  -- 5.0 s
    , Event 24.0
    ]
  
  utils_t15 = take 50 (embed (time >>> sampleWindow 5 0.5)
                             (deltaEncode 0.125 (repeat ())))
  
  utils_t15r =
    [ NoEvent,                     NoEvent, NoEvent, NoEvent  -- 0.0 s
    , Event [0.5],                 NoEvent, NoEvent, NoEvent  -- 0.5 s
    , Event [0.5,1.0],             NoEvent, NoEvent, NoEvent  -- 1.0 s
    , Event [0.5,1.0,1.5],         NoEvent, NoEvent, NoEvent  -- 1.5 s
    , Event [0.5,1.0,1.5,2.0],     NoEvent, NoEvent, NoEvent  -- 2.0 s
    , Event [0.5,1.0,1.5,2.0,2.5], NoEvent, NoEvent, NoEvent  -- 2.5 s
    , Event [1.0,1.5,2.0,2.5,3.0], NoEvent, NoEvent, NoEvent  -- 3.0 s
    , Event [1.5,2.0,2.5,3.0,3.5], NoEvent, NoEvent, NoEvent  -- 3.5 s
    , Event [2.0,2.5,3.0,3.5,4.0], NoEvent, NoEvent, NoEvent  -- 4.0 s
    , Event [2.5,3.0,3.5,4.0,4.5], NoEvent, NoEvent, NoEvent  -- 4.5 s
    , Event [3.0,3.5,4.0,4.5,5.0], NoEvent, NoEvent, NoEvent  -- 5.0 s
    , Event [3.5,4.0,4.5,5.0,5.5], NoEvent, NoEvent, NoEvent  -- 5.5 s
    , Event [4.0,4.5,5.0,5.5,6.0], NoEvent                    -- 6.0 s
    ]
  
  {-
  -- Not robust
  utils_t16 = take 50 (embed (time >>> sampleWindow 5 0.5) input)
    where
      input = ((), [(dt, Just ()) | dt <- dts])
  
      dts = replicate 15 0.1
            ++ [1.0, 1.0]
            ++ replicate 15 0.1
            ++ [2.0]
            ++ replicate 10 0.1
  
  utils_t16r =
    [ NoEvent, NoEvent,          NoEvent, NoEvent, NoEvent             -- 0.0
    , NoEvent, Event [0.6],      NoEvent, NoEvent, NoEvent             -- 0.5
    , NoEvent, Event [0.6, 1.1], NoEvent, NoEvent, NoEvent             -- 1.0
    , NoEvent                                                          -- 1.5
    , Event [0.6,1.1,2.5,2.5,2.5]                                      -- 2.5
    , Event [2.5,2.5,2.5,3.5,3.5], NoEvent, NoEvent, NoEvent, NoEvent  -- 3.5
    , NoEvent, Event [2.5,2.5,3.5,3.5,4.1], NoEvent, NoEvent, NoEvent  -- 4.0
    , NoEvent, Event [2.5,3.5,3.5,4.1,4.6], NoEvent, NoEvent, NoEvent  -- 4.5
    , NoEvent                                                          -- 5.0
    , Event [7.0,7.0,7.0,7.0,7.0], NoEvent, NoEvent, NoEvent, NoEvent  -- 7.0
    , NoEvent, Event [7.0,7.0,7.0,7.0,7.6], NoEvent, NoEvent, NoEvent  -- 7.5
    , NoEvent                                                          -- 8.0
    ]
  -}
  
  utils_t16 = take 50 (embed (time >>> sampleWindow 5 0.4999) input)
    where
      input = ((), [(dt, Just ()) | dt <- dts])
  
      dts = replicate 15 0.1
            ++ [1.0, 1.0]
            ++ replicate 15 0.1
            ++ [2.0]
            ++ replicate 10 0.1
  
  utils_t16r =
    [ NoEvent,          NoEvent, NoEvent, NoEvent, NoEvent        -- 0.0
    , Event [0.5],      NoEvent, NoEvent, NoEvent, NoEvent        -- 0.5
    , Event [0.5, 1.0], NoEvent, NoEvent, NoEvent, NoEvent        -- 1.0
    , Event [0.5, 1.0, 1.5]                                       -- 1.5
    , Event [0.5, 1.0, 1.5, 2.5, 2.5]                             -- 2.5
    , Event [1.5, 2.5, 2.5, 3.5, 3.5], NoEvent, NoEvent, NoEvent  -- 3.5
    ,                                                    NoEvent
    , Event [2.5, 2.5, 3.5, 3.5, 4.0], NoEvent, NoEvent, NoEvent  -- 4.0
    ,                                                    NoEvent
    , Event [2.5, 3.5, 3.5, 4.0, 4.5], NoEvent, NoEvent, NoEvent  -- 4.5
    ,                                                    NoEvent
    , Event [3.5, 3.5, 4.0, 4.5, 5.0]                             -- 5.0
    , Event [5.0, 7.0, 7.0, 7.0, 7.0], NoEvent, NoEvent, NoEvent  -- 7.0
    ,                                                    NoEvent
    , Event [7.0, 7.0, 7.0, 7.0, 7.5], NoEvent, NoEvent, NoEvent  -- 7.5
    ,                                                    NoEvent
    , Event [7.0, 7.0, 7.0, 7.5, 8.0]                             -- 8.0
    ]
  
  -- * Repetition and switching
  
  utils_t13 :: [Event ()]
  utils_t13 = testSF1 (recur (after 0.99 ()))
  
  utils_t13r =
    [ NoEvent,  NoEvent, NoEvent, NoEvent  -- 0.0 s
    , Event (), NoEvent, NoEvent, NoEvent  -- 1.0 s
    , Event (), NoEvent, NoEvent, NoEvent  -- 2.0 s
    , Event (), NoEvent, NoEvent, NoEvent  -- 3.0 s
    , Event (), NoEvent, NoEvent, NoEvent  -- 4.0 s
    , Event (), NoEvent, NoEvent, NoEvent  -- 5.0 s
    , Event ()
    ]
  
  utils_t14 :: [Event Int]
  utils_t14 = testSF1 (after 1.0 1 `andThen` now 2 `andThen` after 2.0 3)
  
  utils_t14r =
    [ NoEvent, NoEvent, NoEvent, NoEvent  -- 0.0 s
    , Event 1, NoEvent, NoEvent, NoEvent  -- 1.0 s
    , NoEvent, NoEvent, NoEvent, NoEvent  -- 2.0 s
    , Event 3, NoEvent, NoEvent, NoEvent  -- 3.0 s
    , NoEvent, NoEvent, NoEvent, NoEvent  -- 4.0 s
    , NoEvent, NoEvent, NoEvent, NoEvent  -- 5.0 s
    , NoEvent
    ]
  
  -- * Auxiliary
  
  -- prop :: SF a b -> (a -> b ->
  prop (a,b) = SP ((identity &&& a) >>^ uncurry b)
  
  -- * Arbitrary value generation
  
  instance Arbitrary a => Arbitrary (Event a) where
    arbitrary = oneof [ return NoEvent
                      , do x <- arbitrary
                           return $ Event x
                      ]
  