diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,40 @@
+0.4.2.0
+-------
+<https://github.com/mstksg/auto/releases/tag/v0.4.2.0>
+
+*   Removed all upper bounds on dependencies.
+*   **Control.Auto.Blip**: Companions to `emitJusts` and `onJusts` added, for
+    `Either`: `emitEithers` and `onEithers`.  Emit every item inputted, but
+    fork them into one of two output blit streams based on `Right` or `Left`
+    properties.  Only preserves blip semantics/makes sense if any given
+    input's `Right` or `Left`ness is expected to be independent from the last
+    received one.
+*   **Control.Auto.Blip**: New "blip stream collapsers", `asMaybes` and
+    `substituteB`.  `asMaybes` turns a blip stream into a stream of `Maybe`s,
+    `Just` when something was emitted, and `Nothing` when not.  `substituteB`
+    takes a regular stream and a blip stream, and outputs the values of the
+    regular stream whenever the blip stream doesn't emit and the emitted value
+    when it does --- basically a more powerful version of `fromBlips`, where
+    the "default" value now comes from a stream instead of being always the
+    same.
+*   **Control.Auto.Blip**: New blip stream creator, `collectN`, which emits
+    every `n` steps with the last `n` items received.
+*   **Control.Auto.Blip**: New blip stream modifiers, `collectB` and
+    `collectBs`.   `collectB` waits on two blip streams and emits after it has
+    received something from *both*.  `collectBs` is like `collectN`, except
+    emits after every `n` emitted values received with the past `n` emitted
+    values.
+*   **Control.Auto.Collection**: "Intervaled" counterparts to `mux` and
+    `muxMany`, `muxI` and `muxManyI`.  They store `Interval`s instead of
+    `Auto`s...and when the `Interval`s turned "off", they are removed from the
+    collection.
+*   **Control.Auto.Switch**: A new "count-down" swithcer, `switchIn`, which
+    acts a bit like `(-->)` and `(-?>)`, except the switch happens
+    deterministically after a pre-set given number of steps.  Act like the
+    first `Auto` for a given number of steps, and then act like the second
+    ever after.  Basically a direct implementation of the common
+    `onFor n a1 --> a2` idiom.
+
 0.4.1.0
 -------
 <https://github.com/mstksg/auto/releases/tag/v0.4.1.0>
@@ -5,10 +42,10 @@
 *   Adapted to more consistent semantic versioning scheme, where the third
     number is a new update, and the fourth number is reserved for bug fixes.
 *   **Control.Auto.Blip**: `foldrB` and `foldlB'` officially **deprecated** in
-    their current forms.  From `0.5`, they will have corrected functionality
-    and a new type signature.  The current functionality doesn't really make
-    sense, and was a mistake during their implementation.  You can begin using
-    the new versions now, with:
+    their current forms.  From version `0.5`, they will have corrected
+    functionality and a new type signature.  The current functionality doesn't
+    really make sense, and was a mistake during their implementation.  You can
+    begin using the new versions now, with:
 
     ```
     foldrB  = foldr  (merge f) mempty
diff --git a/auto.cabal b/auto.cabal
--- a/auto.cabal
+++ b/auto.cabal
@@ -1,5 +1,5 @@
 name:                auto
-version:             0.4.1.0
+version:             0.4.2.0
 synopsis:            Denotative, locally stateful programming DSL & platform
 description:         (Up to date documentation is maintained at
                      <https://mstksg.github.com/auto>)
@@ -41,7 +41,7 @@
                      repository on github for plenty of real-world and toy
                      examples to learn from; I've also done a
                      <blog.jle.im/entries/series/+all-about-auto blog series>
-                     on this library, for examples and full tutorials!
+                     on this library, with examples and full tutorials!
                      .
                      Support available on freenode's #haskell-auto,
                      #haskell-game, and also on the github issue
@@ -85,16 +85,16 @@
                      , Control.Auto.Time
   -- other-modules:
   -- other-extensions:
-  build-depends:       base         >= 4.6      && < 4.9
-                     , MonadRandom  >= 0.3.0.1  && < 0.4
-                     , bytestring   >= 0.10.4.0 && < 0.11
-                     , cereal       >= 0.4.1.1  && < 0.5
-                     , containers   >= 0.5.5.1  && < 0.6
-                     , deepseq      >= 1.3.0.2  && < 2.0
-                     , profunctors  >= 4.3      && < 5.0
-                     , random       >= 1.1      && < 2.0
-                     , semigroups   >= 0.16     && < 0.17
-                     , transformers >= 0.4.2.0  && < 0.5
+  build-depends:       base         >= 4.6      && < 5
+                     , MonadRandom  >= 0.3.0.1
+                     , bytestring   >= 0.10.4.0
+                     , cereal       >= 0.4.1.1
+                     , containers   >= 0.5.5.1
+                     , deepseq      >= 1.3.0.2
+                     , profunctors  >= 4.3
+                     , random       >= 1.1
+                     , semigroups   >= 0.16
+                     , transformers >= 0.4.2.0
   hs-source-dirs:      src
   default-language:    Haskell2010
   ghc-options:         -Wall
diff --git a/src/Control/Auto/Blip.hs b/src/Control/Auto/Blip.hs
--- a/src/Control/Auto/Blip.hs
+++ b/src/Control/Auto/Blip.hs
@@ -31,15 +31,19 @@
   , mergeRs
   , foldrB
   , foldlB'
-  -- ** Blip stream creation (dangerous!)
+  -- ** "Raw" blip stream creation (dangerous!)
   , emitJusts
-  , emitOn
+  , emitEithers
   , onJusts
+  , onEithers
+  , emitOn
   -- ** Blip stream collapse
   , fromBlips
   , fromBlipsWith
+  , asMaybes
   , holdWith
   , holdWith_
+  , substituteB
   -- * Step/"time" based Blip streams and generators
   , never
   , immediately
@@ -47,6 +51,8 @@
   , every
   , eachAt
   , eachAt_
+  , collectN
+  , collectN_
   -- * Modifying Blip streams
   , tagBlips
   , modifyBlips
@@ -58,6 +64,10 @@
   , lagBlips_
   , filterB
   , splitB
+  , collectB
+  , collectB_
+  , collectBs
+  , collectBs_
   , joinB
   , mapMaybeB
   , takeB
@@ -293,6 +303,9 @@
 --
 foldrB :: (a -> a -> a) -> a -> [Blip a] -> Blip a
 foldrB f x0 = foldr (merge f) (Blip x0)
+{-# DEPRECATED foldrB "Starting in v0.5, will have new functionality." #-}
+
+
 -- foldrB :: (a -> a -> a) -> [Blip a] -> Blip a
 -- foldrB f = foldr (merge f) NoBlip
 
@@ -319,6 +332,8 @@
 -- @
 foldlB' :: (a -> a -> a) -> a -> [Blip a] -> Blip a
 foldlB' f x0 = foldl' (merge f) (Blip x0)
+{-# DEPRECATED foldlB' "Starting in v0.5, will have new functionality." #-}
+
 -- foldlB' :: (a -> a -> a) -> [Blip a] -> Blip a
 -- foldlB' f = foldl' (merge f) NoBlip
 
@@ -386,6 +401,38 @@
     f x (Just i) | i <= 1    = (Blip x, Nothing)
                  | otherwise = (NoBlip, Just (i - 1))
 
+-- | @'collectN' n@ emits every @n@ steps, emitting with the @n@ last items
+-- received.
+--
+-- >>> streamAuto' (collectN 3) [1..10]
+-- [ NoBlip, NoBlip, Blip [1,2,3], NoBlip, NoBlip, Blip [4,5,6]
+-- , NoBlip, NoBlip, Blip [7,8,9], NoBlip ]
+--
+collectN :: Serialize a => Int -> Auto m a (Blip [a])
+collectN (max 1 -> n) = mkState (_collectBsF n . Blip) (n, [])
+
+-- | The non-serializing/non-resuming version of 'collectN'
+collectN_ :: Int -> Auto m a (Blip [a])
+collectN_ (max 1 -> n) = mkState_ (_collectBsF n . Blip) (n, [])
+
+-- | A blip stream that listens to an input blip stream and emits after the
+-- input stream emits a given number of times.  Emits with a list of all
+-- received emitted values.
+collectBs :: Serialize a => Int -> Auto m (Blip a) (Blip [a])
+collectBs (max 1 -> n) = mkState (_collectBsF n) (n, [])
+
+-- | The non-serializing/non-resuming version of 'collectBs'.
+collectBs_ :: Int -> Auto m (Blip a) (Blip [a])
+collectBs_ (max 1 -> n) = mkState_ (_collectBsF n) (n, [])
+
+-- n expected to be strictly positive
+_collectBsF :: Int -> Blip a -> (Int, [a]) -> (Blip [a], (Int, [a]))
+_collectBsF n = f
+  where
+    f (Blip x) (i, xs) | i == 1    = (Blip (reverse (x:xs)), (n    , []  ))
+                       | otherwise = (NoBlip               , (i - 1, x:xs))
+    f _        s       = (NoBlip, s)
+
 -- | Produces a blip stream that emits the input value whenever the input
 -- satisfies a given predicate.
 --
@@ -507,6 +554,34 @@
 joinB :: Auto m (Blip (Blip a)) (Blip a)
 joinB = mkFunc (blip NoBlip id)
 
+-- | Waits on two streams, and emits with the first seen items when both
+-- have emitted.  Once it emits, starts over.
+--
+-- >>> streamAuto' collectB [(Blip 1, NoBlip), (Blip 2, Blip 'a'),(Blip 3, Blip 'b')]
+-- [NoBlip, Blip (1, 'a'), Blip (3, 'b')]
+--
+-- Can be used to implement a sort of "parallel wait".
+--
+collectB :: (Serialize a, Serialize b)
+         => Auto m (Blip a, Blip b) (Blip (a, b))
+collectB = mkState _collectBF (Nothing, Nothing)
+
+-- | The non-serializing/non-resuming version of 'collectB'.
+collectB_ :: Auto m (Blip a, Blip b) (Blip (a, b))
+collectB_ = mkState_ _collectBF (Nothing, Nothing)
+
+_collectBF :: (Blip a, Blip b)
+           -> (Maybe a, Maybe b)
+           -> (Blip (a, b), (Maybe a, Maybe b))
+_collectBF (b1, b2) (st1, st2) =
+    case liftA2 (,) st1' st2' of
+      Just (x, y) -> (Blip (x, y), (Nothing, Nothing))
+      Nothing     -> (NoBlip     , (st1'   , st2'   ))
+  where
+    st1' = st1 <|> blip Nothing Just b1
+    st2' = st2 <|> blip Nothing Just b2
+
+
 -- | Applies the given function to every emitted value, and suppresses all
 -- those for which the result is 'Nothing'.  Otherwise, lets it pass
 -- through with the value in the 'Just'.
@@ -756,16 +831,40 @@
 -- semantics, we have "Control.Auto.Interval".
 --
 -- See the examples of 'emitOn' for more concrete good/bad use cases.
+--
+-- prop> onJusts == emitJusts id
 onJusts :: Auto m (Maybe a) (Blip a)
 onJusts = mkFunc (maybe NoBlip Blip)
 
+-- | Like 'onJusts', except forks into two streams depending on if the
+-- input is 'Left' or 'Right'.
+--
+-- Is only meaningful if you expect every 'Left'/'Right' choice to be
+-- independent of the last.
+--
+-- prop> onEithers == emitEithers id
+onEithers :: Auto m (Either a b) (Blip a, Blip b)
+onEithers = mkFunc $ \ex -> case ex of
+                              Left x  -> (Blip x, NoBlip)
+                              Right x -> (NoBlip, Blip x)
+
+-- | Like 'emitJusts', except forks into two streams depending on the
+-- function's result being 'Left' or 'Right'.
+--
+-- Is only meaningful if you expect every 'Left'/'Right' choice to be
+-- independent of the last.
+emitEithers :: (a -> Either b c) -> Auto m a (Blip b, Blip c)
+emitEithers f = mkFunc $ \x -> case f x of
+                                 Left y  -> (Blip y, NoBlip)
+                                 Right y -> (NoBlip, Blip y)
+
 -- | @'fromBlips' d@ is an 'Auto' that decomposes the incoming blip
 -- stream by constantly outputting @d@ except when the stream emits, and
 -- outputs the emitted value when it does.
 fromBlips :: a  -- ^ the "default value" to output when the input is not
                 --   emitting.
           -> Auto m (Blip a) a
-fromBlips d = mkFunc (blip d id)
+fromBlips d = mkFunc $ blip d id
 
 -- | @'fromBlipsWith' d f@ is an 'Auto' that decomposes the incoming blip
 -- stream by constantly outputting @d@ except when the stream emits, and
@@ -775,8 +874,17 @@
               -> (a -> b)   -- ^ the function to apply to the emitted value
                             --   whenever input is emitting.
               -> Auto m (Blip a) b
-fromBlipsWith d f = mkFunc (blip d f)
+fromBlipsWith d f = mkFunc $ blip d f
 
+-- | Collapse a blip stream of `a`s into a stream of `Maybe a`'s
+asMaybes :: Auto m (Blip a) (Maybe a)
+asMaybes = mkFunc $ blip Nothing Just
+
+-- | Take in a normal stream and a blip stream.  Behave like the normal
+-- stream when the blip stream doesn't emit...but when it does, output the
+-- emitted value instead.
+substituteB :: Auto m (a, Blip a) a
+substituteB = mkFunc $ \(x, b) -> blip x id b
 
 -- | @'holdWith' y0@ is an 'Auto' whose output is always the /most recently
 -- emitted/ value from the input blip stream.  Before anything is emitted,
diff --git a/src/Control/Auto/Collection.hs b/src/Control/Auto/Collection.hs
--- a/src/Control/Auto/Collection.hs
+++ b/src/Control/Auto/Collection.hs
@@ -61,9 +61,13 @@
   -- ** Single input, single output
   , mux
   , mux_
+  , muxI
+  , muxI_
   -- ** Multiple input, multiple output
   , muxMany
   , muxMany_
+  , muxManyI
+  , muxManyI_
   -- * "Gathering"/accumulating collections
   -- ** Single input, multiple output
   , gather
@@ -351,10 +355,6 @@
 -- Whenever any of the internal 'Auto's return 'Nothing', they are removed
 -- from the collection.
 --
--- Toy examples here are of limited use, but let's try it out.  Here we
--- will have a 'dynMap_' that feeds each internal 'Auto' back to itself.
--- The result of each is sent directly back to itself.
---
 -- >>> import qualified Data.IntMap as IM
 -- >>> let dm0 :: Auto' (IM.IntMap Int) (IM.IntMap Int)
 --         dm0 = proc x -> do
@@ -530,8 +530,8 @@
 --
 -- See 'mux' for more notes.
 muxMany :: (Serialize k, Ord k, Monad m)
-        => (k -> Auto m a b)    -- ^ function to create a new 'Auto' if
-                                --   none at that key already exists
+        => (k -> Auto m a b)  -- ^ function to create a new 'Auto' if
+                              --   none at that key already exists
         -> Auto m (Map k a) (Map k b)
 muxMany f = go mempty
   where
@@ -545,21 +545,21 @@
     t     = _muxManyF f go
 
 -- | The non-serializing/non-resuming version of 'muxMany'.
-muxMany_ :: forall m a b k. (Ord k, Monad m)
-         => (k -> Auto m a b)     -- ^ function to create a new 'Auto' if
-                                  --   none at that key already exists
+muxMany_ :: (Ord k, Monad m)
+         => (k -> Auto m a b) -- ^ function to create a new 'Auto' if
+                              --   none at that key already exists
          -> Auto m (Map k a) (Map k b)
 muxMany_ f = go mempty
   where
-    go :: Map k (Auto m a b) -> Auto m (Map k a) (Map k b)
+    -- go :: Map k (Auto m a b) -> Auto m (Map k a) (Map k b)
     go = mkAutoM_ . _muxManyF f go
 
 _muxManyF :: forall k m a b. (Ord k, Monad m)
-          => (k -> Auto m a b)                           -- ^ f : make new Autos
+          => (k -> Auto m a b)                          -- ^ f : make new Autos
           -> (Map k (Auto m a b) -> Auto m (Map k a) (Map k b)) -- ^ go: make next step
-          -> Map k (Auto m a b)                          -- ^ as: all current Autos
-          -> Map k a                                     -- ^ xs: Inputs
-          -> m (Map k b, Auto m (Map k a) (Map k b))     -- ^ Outputs, and next Auto.
+          -> Map k (Auto m a b)                         -- ^ as: all current Autos
+          -> Map k a                                    -- ^ xs: Inputs
+          -> m (Map k b, Auto m (Map k a) (Map k b))    -- ^ Outputs, and next Auto.
 _muxManyF f go as xs = do
     -- all the outputs of the autos with the present inputs; autos without
     --   inputs are ignored.
@@ -578,6 +578,86 @@
     --   corresponding input.
     steps :: Map k (m (b, Auto m a b))
     steps = M.intersectionWith stepAuto allas xs
+
+
+-- | Like 'muxI', but holds 'Interval's instead.  When any given 'Interval'
+-- turns "off", it's removed from the collection.  If its key is fed in
+-- again, it'll be restarted with the initializing function.  On the actual
+-- step when it turns "off", 'Nothing' will be returned.
+muxI :: (Serialize k, Ord k, Monad m)
+     => (k -> Interval m a b) -- ^ function to create a new 'Auto' if none at
+                              --   that key already exists.
+     -> Auto m (k, a) (Maybe b)
+muxI f = dimap (uncurry M.singleton) (listToMaybe . M.elems) (muxManyI f)
+
+-- | The non-serializing/non-resuming version of 'muxI'.
+muxI_ :: (Ord k, Monad m)
+      => (k -> Interval m a b)   -- ^ function to create a new 'Auto' if none at
+                                 --   that key already exists
+      -> Auto m (k, a) (Maybe b)
+muxI_ f = dimap (uncurry M.singleton) (listToMaybe . M.elems) (muxManyI_ f)
+
+-- | Like 'muxManyI', but holds 'Interval's instead.  When any given
+-- 'Interval' turns "off", it's removed from the collection.  Only
+-- 'Interval's that are "on" after the step will be present in the output
+-- 'Map'.
+muxManyI :: (Serialize k, Ord k, Monad m)
+         => (k -> Interval m a b) -- ^ function to create a new 'Auto' if
+                                  --   none at that key already exists
+         -> Auto m (Map k a) (Map k b)
+muxManyI f = go mempty
+  where
+    -- go :: Map k (Interval m a b) -> Auto m (Map k a) (Map k b)
+    go as = mkAutoM l (s as) (t as)
+    l     = do
+      ks <- get
+      let as = M.fromList (map (id &&& f) ks)
+      go <$> mapM resumeAuto as
+    s as  = put (M.keys as) *> mapM_ saveAuto as
+    t     = _muxManyIF f go
+
+-- | The non-serializing/non-resuming version of 'muxManyI'.
+muxManyI_ :: (Ord k, Monad m)
+          => (k -> Interval m a b) -- ^ function to create a new 'Auto' if
+                                   --   none at that key already exists
+          -> Auto m (Map k a) (Map k b)
+muxManyI_ f = go mempty
+  where
+    -- go :: Map k (Interval m a b) -> Auto m (Map k a) (Map k b)
+    go = mkAutoM_ . _muxManyIF f go
+
+_muxManyIF :: forall k m a b. (Ord k, Monad m)
+           => (k -> Interval m a b)                       -- ^ f : make new Autos
+           -> (Map k (Interval m a b) -> Auto m (Map k a) (Map k b)) -- ^ go: make next step
+           -> Map k (Interval m a b)                      -- ^ as: all current Autos
+           -> Map k a                                     -- ^ xs: Inputs
+           -> m (Map k b, Auto m (Map k a) (Map k b))     -- ^ Outputs, and next Auto.
+_muxManyIF f go as xs = do
+    -- all the outputs of the autos with the present inputs; autos without
+    --   inputs are ignored.
+    outs <- sequence steps
+    let outs'  = M.mapMaybe filterDead outs   -- Nothings removed
+        ys     = fmap fst outs'
+        allas' = M.union (fmap snd outs') leftOuts
+    return (ys, go allas')
+  where
+    -- new Autos, from the function.  Only on new ones not found in `as`.
+    newas :: Map k (Interval m a b)
+    newas = M.mapWithKey (\k _ -> f k) (M.difference xs as)
+    -- all Autos, new and old.  Prefer the old ones.
+    allas :: Map k (Interval m a b)
+    allas = M.union as newas
+    -- Step all the autos with all the inputs.  Lose the Autos that have no
+    --   corresponding input.
+    steps :: Map k (m (Maybe b, Interval m a b))
+    steps = M.intersectionWith stepAuto allas xs
+    -- Autos not being stepped
+    leftOuts :: Map k (Interval m a b)
+    leftOuts = M.difference allas steps
+    -- Get out the result if Just, otherwise erase it all.
+    filterDead :: (Maybe b, Interval m a b) -> Maybe (b, Interval m a b)
+    filterDead (Just x, i) = Just (x, i)
+    filterDead _           = Nothing
 
 e2m :: Either (a, b) b -> (Maybe a, b)
 e2m (Left (x, y)) = (Just x , y)
diff --git a/src/Control/Auto/Core.hs b/src/Control/Auto/Core.hs
--- a/src/Control/Auto/Core.hs
+++ b/src/Control/Auto/Core.hs
@@ -827,7 +827,7 @@
 --         Nothing -> do
 --           (y, a2') <- stepAuto a2 x
 --           return (y, switched a2')
---     switched a = mkAutoM (switched <$> resumeAuto a)
+--     switched a = mkAutoM l
 --                          (put True  *> saveAuto a)
 --                        $ \x -> do
 --                            (y, a') <- stepAuto a x
@@ -1172,6 +1172,19 @@
 --
 -- (Compare with the example in 'accum')
 --
+-- Note that this is more or less an encoding of 'scanl', that can be
+-- "decoded" with 'streamAuto'':
+--
+-- >>> let myScanl f z = streamAuto' (accumD f z)
+-- >>> scanl (+) 0 [1..10]
+-- [0,3,6,10,15,21,28,36,45,55]
+-- >>> myScanl (+) 0 [1..10]
+-- [0,3,6,10,15,21,28,36,45]
+--
+-- The only difference is that you don't get the last element.  (You could
+-- force it out, if you wanted, by feeding any nonsense value in --- even
+-- 'undefined'! --- and getting the result)
+--
 accumD :: Serialize b
          => (b -> a -> b)      -- ^ accumulating function
          -> b                  -- ^ initial accumulator
@@ -1308,8 +1321,8 @@
 
 -- | When the underlying 'Monad'/'Applicative' @m@ is an 'Alternative',
 -- fork the input through each one and "squish" their results together
--- inside the 'Alternative' context.  Somewhat rarely used, because who
--- uses an 'Alternative' @m@?
+-- inside the 'Alternative' context.  See 'runTraversableA' for similar use
+-- cases.
 --
 -- >>> streamAuto (arrM (mfilter even . Just)) [1..10]
 -- Nothing
diff --git a/src/Control/Auto/Effects.hs b/src/Control/Auto/Effects.hs
--- a/src/Control/Auto/Effects.hs
+++ b/src/Control/Auto/Effects.hs
@@ -898,11 +898,15 @@
 -- bar = arrM Just
 -- @
 --
+-- >>> streamAuto foo [2,4,6,7]
+-- Nothing
+-- >>> streamAuto' (runTraversableA foo) [2,4,6,7]
+-- [Just 1, Just 2, Just 3, Nothing]
 -- >>> streamAuto (foo &&& bar) [2,4,6]
 -- Just [(1, 2),(2, 4),(3, 6)]
 -- >>> streamAuto (foo &&& bar) [2,4,6,7]
 -- Nothing
--- >>> streamAuto' ('runTraversableA' foo '<|?>' 'runTraversableA' bar) [2,4,6,7]
+-- >>> streamAuto' (runTraversableA foo <|?> runTraversableA bar) [2,4,6,7]
 -- [Just 1, Just 2, Just 3, Just 7]
 runTraversableA :: (Monad f, Traversable f)
                 => Auto f a b           -- ^ 'Auto' run over traversable structure
@@ -915,6 +919,7 @@
                               y  = liftM fst o
                               a' = liftM snd o
                           in  (y, go a')
+
 
 -- | Wraps a "try" over an underlying 'IO' monad; if the Auto encounters a
 -- runtime exception while trying to "step" itself, it'll output a 'Left'
diff --git a/src/Control/Auto/Interval.hs b/src/Control/Auto/Interval.hs
--- a/src/Control/Auto/Interval.hs
+++ b/src/Control/Auto/Interval.hs
@@ -243,7 +243,7 @@
 --     'bindI' i2 . i1 :: 'Interval' m a b c
 -- @
 --
--- >>> let a1        = when (< 5) `compI` offFor 2
+-- >>> let a1        = whenI (< 5) `compI` offFor 2
 -- >>> streamAuto' a1 [1..6]
 -- [Nothing, Nothing, Just 3, Just 4, Nothing, Nothing]
 --
@@ -743,3 +743,4 @@
       -> Interval m a b   -- ^ ...to this one
       -> Interval m a c
 compI f g = fmap join (during f) . g
+
diff --git a/src/Control/Auto/Switch.hs b/src/Control/Auto/Switch.hs
--- a/src/Control/Auto/Switch.hs
+++ b/src/Control/Auto/Switch.hs
@@ -33,6 +33,7 @@
   -- * Sequential switching
     (-->)
   , (-?>)
+  , switchIn
   -- * Arbitrary switching
   , switchFrom_
   , switchOn_
@@ -153,12 +154,46 @@
         Nothing -> do
           (y, a2') <- stepAuto a2 x
           return (y, switched a2')
-    switched a = mkAutoM (switched <$> resumeAuto a)
+    switched a = mkAutoM l
                          (put True  *> saveAuto a)
                        $ \x -> do
                            (y, a') <- stepAuto a x
                            return (y, switched a')
 -- TODO: Add tests for the serialization here.
+
+-- | @'switchIn' n a1 a2@ will behave like @a1@ for @n@ steps of output,
+-- and then behave like @a2@ forever after.
+--
+-- More or less a more efficient/direct implementation of the common idiom:
+--
+-- @
+-- onFor n a1 --> a2
+-- @
+--
+--
+switchIn :: Monad m
+         => Int           -- ^ number of outputs before switching
+         -> Auto m a b    -- ^ initial behavior
+         -> Auto m a b    -- ^ switched behavior
+         -> Auto m a b
+switchIn n a1 a2 | n > 0     = mkAutoM l s t
+                 | otherwise = switched a2
+  where
+    l = do
+      flag <- get
+      if flag
+        then resumeAuto (switched a2)
+        else switchIn <$> get <*> resumeAuto a1 <*> pure a2
+    s = put False *> put n *> saveAuto a1
+    t x = do
+      (y, a1') <- stepAuto a1 x
+      return (y, switchIn (n - 1) a1' a2)
+    switched a = mkAutoM l
+                         (put True *> saveAuto a)
+                       $ \x -> do
+                           (y, a') <- stepAuto a x
+                           return (y, switched a')
+
 
 -- | Takes an 'Auto' who has both a normal output stream and a blip stream
 -- output stream, where the blip stream emits new 'Auto's.
diff --git a/src/Control/Auto/Time.hs b/src/Control/Auto/Time.hs
--- a/src/Control/Auto/Time.hs
+++ b/src/Control/Auto/Time.hs
@@ -36,6 +36,7 @@
     count
   , count_
   -- * Manipulating time
+  , priming
   -- ** Delaying
   , lastVal
   , lastVal_
@@ -47,8 +48,6 @@
   , delayList_
   , delayN
   , delayN_
-  -- ** "Priming"
-  , priming
   -- ** Stretching
   , stretch
   , stretch_
