diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,16 +1,33 @@
 # Revision history for reflex
 
-## Unreleased
+## 0.6.2.3
 
+* Add an upper-bound to witherable
+
+## 0.6.2.2
+
+* Support these >= 1. Add `split-these` flag to control whether to use new these/semialign combination or not.
+* Update version bounds to fix some CI failures
+* Add travis CI configuration
+
+## 0.6.2.1
+
 * Generalize `fan` to `fanG` to take a `DMap` with non-`Identity`
-  values.
+  functor:
+    * `fan` to `fanG`
+    * `EventSelectorG` for `fanG` result selector.
 
+* Reduce the amount of unsafeCoerce in coercing newtypes under Event/Dynamic/Behavior.
+    * Add fused ReaderIO for the purpose of coercion (ReaderT's third argument has nominal role preventing automated coerce)
+    * Add incrementalCoercion/coerceIncremental to go with dynamicCoercion/coerceDynamic
+
 * Generalize merging functions:
   `merge` to `mergeG`, 
   `mergeIncremental` to `mergeIncrementalG`, 
-  `distributeDMapOverDynPure` to `distributeDMapOverDynPureG`,
   `mergeIncrementalWithMove` to `mergeIncrementalWithMoveG`.  
 
+* Generalize distribute function:
+    `distributeDMapOverDynPure` to `distributeDMapOverDynPureG`,
 
 ## 0.6.2.0
 
diff --git a/reflex.cabal b/reflex.cabal
--- a/reflex.cabal
+++ b/reflex.cabal
@@ -1,5 +1,5 @@
 Name: reflex
-Version: 0.6.2.1
+Version: 0.6.2.3
 Synopsis: Higher-order Functional Reactive Programming
 Description: Reflex is a high-performance, deterministic, higher-order Functional Reactive Programming system
 License: BSD3
@@ -17,6 +17,10 @@
   Quickref.md
   ChangeLog.md
 
+tested-with:
+  GHC  ==8.0.2 || ==8.2.2 || ==8.4.4 || ==8.6.5,
+  GHCJS ==8.4
+
 flag use-reflex-optimizer
   description: Use the GHC plugin Reflex.Optimizer on some of the modules in the package.  This is still experimental.
   default: False
@@ -37,40 +41,51 @@
   default: False
   manual: True
 
+flag split-these
+  description: Use split these/semialign packages
+  manual:      False
+  default:     True
+
 library
   hs-source-dirs: src
   build-depends:
     MemoTrie == 0.6.*,
     base >= 4.9 && < 4.13,
     bifunctors >= 5.2 && < 5.6,
-    comonad,
-    constraints-extras >= 0.2,
-    containers >= 0.5 && < 0.7,
+    comonad >= 5.0.4 && < 5.1,
+    constraints-extras >= 0.3 && < 0.4,
+    containers >= 0.6 && < 0.7,
     data-default >= 0.5 && < 0.8,
     dependent-map >= 0.3 && < 0.4,
     exception-transformers == 0.4.*,
-    profunctors,
+    profunctors >= 5.3 && < 5.5,
     lens >= 4.7 && < 5,
     monad-control >= 1.0.1 && < 1.1,
-    monoidal-containers >= 0.4 && < 0.6,
     mtl >= 2.1 && < 2.3,
     prim-uniq >= 0.1.0.1 && < 0.2,
-    primitive >= 0.5 && < 0.7,
+    primitive >= 0.5 && < 0.8,
+    profunctors,
     random == 1.1.*,
     ref-tf == 0.4.*,
     reflection == 2.1.*,
     semigroupoids >= 4.0 && < 6,
-    semigroups >= 0.16 && < 0.19,
     stm >= 2.4 && < 2.6,
     syb >= 0.5 && < 0.8,
-    these >= 0.4 && < 0.9,
     time >= 1.4 && < 1.9,
-    transformers >= 0.2,
-    transformers-compat >= 0.3,
+    transformers >= 0.5.6.0 && < 0.6,
     unbounded-delays >= 0.1.0.0 && < 0.2,
-    witherable >= 0.2 && < 0.4
+    witherable >= 0.3 && < 0.3.2
 
+  if flag(split-these)
+    build-depends:     these >= 1 && <1.1,
+                       semialign >=1 && <1.1,
+                       monoidal-containers >= 0.5.0.1 && < 0.6
+  else
+    build-depends:     these >= 0.4 && <0.9,
+                       monoidal-containers == 0.5.0.0
+
   exposed-modules:
+    Control.Monad.ReaderIO
     Data.AppendMap,
     Data.FastMutableIntMap,
     Data.FastWeakBag,
@@ -144,7 +159,7 @@
     other-extensions: TemplateHaskell
   else
     build-depends:
-      dependent-sum == 0.6.*
+      dependent-sum >= 0.6 && < 0.7
 
   if flag(fast-weak) && impl(ghcjs)
     cpp-options: -DGHCJS_FAST_WEAK
@@ -161,14 +176,14 @@
     base,
     bifunctors,
     containers,
-    deepseq >= 1.3 && < 1.5,
+    deepseq,
     dependent-map,
     dependent-sum,
     mtl,
     ref-tf,
     reflex,
     split,
-    transformers >= 0.3
+    transformers
   other-modules:
     Reflex.Bench.Focused
     Reflex.Plan.Pure
@@ -187,7 +202,7 @@
     containers,
     dependent-map,
     dependent-sum,
-    deepseq >= 1.3 && < 1.5,
+    deepseq,
     mtl,
     transformers,
     ref-tf,
@@ -206,7 +221,7 @@
                , directory
                , filepath
                , filemanip
-               , hlint
+               , hlint < 2.1 || >= 2.2.2
   if impl(ghcjs)
     buildable: False
 
@@ -216,7 +231,7 @@
   hs-source-dirs: test
   build-depends: base
                , containers
-               , deepseq >= 1.3 && < 1.5
+               , deepseq
                , dependent-map
                , dependent-sum
                , lens
@@ -225,6 +240,10 @@
                , transformers
                , reflex
                , ref-tf
+
+  if flag(split-these)
+    build-depends: these-lens
+
   other-modules:
     Reflex.Test
     Reflex.TestPlan
@@ -232,13 +251,14 @@
     Reflex.Plan.Pure
     Test.Run
 
+
 test-suite RequesterT
   type: exitcode-stdio-1.0
   main-is: RequesterT.hs
   hs-source-dirs: test
   build-depends: base
                , containers
-               , deepseq >= 1.3 && < 1.5
+               , deepseq
                , dependent-sum
                , dependent-map
                , lens
@@ -247,9 +267,14 @@
                , transformers
                , reflex
                , ref-tf
+
+  if flag(split-these)
+    build-depends: these-lens
+
   other-modules:
     Reflex.TestPlan
     Reflex.Plan.Pure
+    Test.Run
 
 test-suite QueryT
   type: exitcode-stdio-1.0
@@ -259,15 +284,18 @@
                , containers
                , dependent-map
                , dependent-sum
-               , deepseq >= 1.3 && < 1.5
+               , deepseq
                , lens
                , monoidal-containers
                , mtl
                , ref-tf
                , reflex
-               , semigroups
                , these
                , transformers
+
+  if flag(split-these)
+    build-depends: semialign, these-lens
+
   other-modules:
     Test.Run
     Reflex.TestPlan
@@ -282,14 +310,16 @@
                , containers
                , dependent-sum
                , dependent-map
-               , deepseq >= 1.3 && < 1.5
+               , deepseq
                , mtl
                , these
                , transformers
                , reflex
                , ref-tf
-  if impl(ghc < 8)
-    build-depends: semigroups
+
+  if flag(split-these)
+    build-depends: semialign
+
   other-modules:
     Reflex.Plan.Pure
     Reflex.Plan.Reflex
@@ -302,7 +332,7 @@
   hs-source-dirs: test
   build-depends: base
                , containers
-               , deepseq >= 1.3 && < 1.5
+               , deepseq
                , dependent-sum
                , mtl
                , reflex
@@ -321,8 +351,8 @@
   build-depends:
     base,
     containers,
-    criterion >= 1.1 && < 1.6,
-    deepseq >= 1.3 && < 1.5,
+    criterion,
+    deepseq,
     dependent-map,
     dependent-sum,
     ref-tf,
@@ -331,7 +361,7 @@
     reflex,
     split,
     stm,
-    transformers >= 0.3
+    transformers
   other-modules:
     Reflex.TestPlan
     Reflex.Plan.Reflex
@@ -345,9 +375,9 @@
   ghc-options: -Wall -O2 -rtsopts -threaded
   build-depends:
     base,
-    containers >= 0.5 && < 0.7,
-    criterion >= 1.1 && < 1.6,
-    deepseq >= 1.3 && < 1.5,
+    containers,
+    criterion,
+    deepseq,
     dependent-map,
     dependent-sum,
     loch-th,
@@ -359,7 +389,7 @@
     split,
     stm,
     time,
-    transformers >= 0.3
+    transformers
   other-modules:
     Reflex.TestPlan
     Reflex.Plan.Reflex
diff --git a/src/Control/Monad/ReaderIO.hs b/src/Control/Monad/ReaderIO.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Monad/ReaderIO.hs
@@ -0,0 +1,60 @@
+{-# language RoleAnnotations #-}
+{-# language MultiParamTypeClasses #-}
+{-# language FlexibleInstances #-}
+{-# language CPP #-}
+module Control.Monad.ReaderIO
+  (
+    ReaderIO (..)
+  )
+  where
+
+import Control.Monad.Fix
+#if MIN_VERSION_base(4,10,0)
+import Control.Applicative
+#endif
+import Control.Monad
+import Control.Monad.Reader.Class
+import Control.Monad.IO.Class
+
+-- | An approximate clone of @RIO@ from the @rio@ package, but not based on
+-- @ReaderT@. The trouble with @ReaderT@ is that its third type argument has a
+-- @nominal@ role, so we can't coerce through it when it's wrapped in some
+-- other @data@ type. Ugh.
+newtype ReaderIO e a = ReaderIO { runReaderIO :: e -> IO a }
+type role ReaderIO representational representational
+
+instance Functor (ReaderIO e) where
+  fmap = liftM
+  {-# INLINE fmap #-}
+  a <$ m = m >> pure a
+  {-# INLINE (<$) #-}
+
+instance Applicative (ReaderIO e) where
+  pure a = ReaderIO $ \_ -> pure a
+  {-# INLINE pure #-}
+  (<*>) = ap
+  {-# INLINE (<*>) #-}
+#if MIN_VERSION_base(4,10,0)
+  liftA2 = liftM2
+  {-# INLINE liftA2 #-}
+#endif  
+  (*>) = (>>)
+  {-# INLINE (*>) #-}
+
+instance Monad (ReaderIO e) where
+  ReaderIO q >>= f = ReaderIO $ \e -> q e >>= \a -> runReaderIO (f a) e
+  {-# INLINE (>>=) #-}
+
+instance MonadFix (ReaderIO e) where
+  mfix f = ReaderIO $ \e -> mfix $ \r -> runReaderIO (f r) e
+  {-# INLINE mfix #-}
+
+instance MonadIO (ReaderIO e) where
+  liftIO m = ReaderIO $ \_ -> m
+  {-# INLINE liftIO #-}
+
+instance MonadReader e (ReaderIO e) where
+  ask = ReaderIO pure
+  {-# INLINE ask #-}
+  local f (ReaderIO m) = ReaderIO (m . f)
+  {-# INLINE local #-}
diff --git a/src/Data/AppendMap.hs b/src/Data/AppendMap.hs
--- a/src/Data/AppendMap.hs
+++ b/src/Data/AppendMap.hs
@@ -46,8 +46,10 @@
 pattern AppendMap :: Map k v -> MonoidalMap k v
 pattern AppendMap m = MonoidalMap m
 
+#if !MIN_VERSION_witherable(0,3,2)
 instance W.Filterable (MonoidalMap k) where
   mapMaybe = mapMaybe
+#endif
 
 -- | Deletes a key, returning 'Nothing' if the result is empty.
 nonEmptyDelete :: Ord k => k -> MonoidalMap k a -> Maybe (MonoidalMap k a)
diff --git a/src/Data/Functor/Misc.hs b/src/Data/Functor/Misc.hs
--- a/src/Data/Functor/Misc.hs
+++ b/src/Data/Functor/Misc.hs
@@ -4,7 +4,6 @@
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE GADTs #-}
-{-# LANGUAGE KindSignatures #-}
 {-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE PatternSynonyms #-}
diff --git a/src/Reflex/Adjustable/Class.hs b/src/Reflex/Adjustable/Class.hs
--- a/src/Reflex/Adjustable/Class.hs
+++ b/src/Reflex/Adjustable/Class.hs
@@ -3,7 +3,6 @@
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE FunctionalDependencies #-}
 {-# LANGUAGE LambdaCase #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeFamilies #-}
diff --git a/src/Reflex/BehaviorWriter/Class.hs b/src/Reflex/BehaviorWriter/Class.hs
--- a/src/Reflex/BehaviorWriter/Class.hs
+++ b/src/Reflex/BehaviorWriter/Class.hs
@@ -5,7 +5,6 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE FunctionalDependencies #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE UndecidableInstances #-}
 #ifdef USE_REFLEX_OPTIMIZER
 {-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
diff --git a/src/Reflex/Class.hs b/src/Reflex/Class.hs
--- a/src/Reflex/Class.hs
+++ b/src/Reflex/Class.hs
@@ -7,7 +7,6 @@
 {-# LANGUAGE FunctionalDependencies #-}
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE LambdaCase #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE NoMonomorphismRestriction #-}
 {-# LANGUAGE PolyKinds #-}
 {-# LANGUAGE RankNTypes #-}
@@ -37,6 +36,7 @@
   , coerceBehavior
   , coerceEvent
   , coerceDynamic
+  , coerceIncremental
   , MonadSample (..)
   , MonadHold (..)
     -- ** 'fan' related types
@@ -173,6 +173,14 @@
   , slowHeadE
   ) where
 
+#if defined(MIN_VERSION_semialign)
+import Prelude hiding (zip, zipWith)
+
+#if MIN_VERSION_these(0,8,0)
+import Data.These.Combinators (justThese)
+#endif
+#endif
+
 import Control.Applicative
 import Control.Monad.Identity
 import Control.Monad.Reader
@@ -312,6 +320,10 @@
   -- | Construct a 'Coercion' for a 'Dynamic' given an 'Coercion' for its
   -- occurrence type
   dynamicCoercion :: Coercion a b -> Coercion (Dynamic t a) (Dynamic t b)
+  -- | Construct a 'Coercion' for an 'Incremental' given 'Coercion's for its
+  -- patch target and patch types.
+  incrementalCoercion
+    :: Coercion (PatchTarget a) (PatchTarget b) -> Coercion a b -> Coercion (Incremental t a) (Incremental t b)
   mergeIntIncremental :: Incremental t (PatchIntMap (Event t a)) -> Event t (IntMap a)
   fanInt :: Event t (IntMap a) -> EventSelectorInt t a
 
@@ -345,6 +357,12 @@
 coerceDynamic :: (Reflex t, Coercible a b) => Dynamic t a -> Dynamic t b
 coerceDynamic = coerceWith $ dynamicCoercion Coercion
 
+-- | Coerce an 'Incremental' between representationally-equivalent value types
+coerceIncremental
+  :: (Reflex t, Coercible a b, Coercible (PatchTarget a) (PatchTarget b))
+  => Incremental t a -> Incremental t b
+coerceIncremental = coerceWith $ incrementalCoercion Coercion Coercion
+
 -- | Construct a 'Dynamic' from a 'Behavior' and an 'Event'.  The 'Behavior'
 -- __must__ change when and only when the 'Event' fires, such that the
 -- 'Behavior''s value is always equal to the most recent firing of the 'Event';
@@ -669,11 +687,7 @@
 instance (Reflex t, Semigroup a) => Semigroup (Behavior t a) where
   a <> b = pull $ liftM2 (<>) (sample a) (sample b)
   sconcat = pull . fmap sconcat . mapM sample
-#if MIN_VERSION_semigroups(0,17,0)
   stimes n = fmap $ stimes n
-#else
-  times1p n = fmap $ times1p n
-#endif
 
 -- | Alias for 'mapMaybe'
 fmapMaybe :: Filterable f => (a -> Maybe b) -> f a -> f b
@@ -700,10 +714,13 @@
 instance Reflex t => Alt (Event t) where
   ev1 <!> ev2 = leftmost [ev1, ev2]
 
--- | 'Event' intersection (convenient interface to 'coincidence').
+-- | 'Event' intersection. Only occurs when both events are co-incident.
 instance Reflex t => Apply (Event t) where
-  evf <.> evx = coincidence (fmap (<$> evx) evf)
+  evf <.> evx = mapMaybe f (align evf evx) where
+    f (These g a) = Just (g a)
+    f _           = Nothing
 
+
 -- | 'Event' intersection (convenient interface to 'coincidence').
 instance Reflex t => Bind (Event t) where
   evx >>- f = coincidence (f <$> evx)
@@ -871,11 +888,7 @@
 instance (Semigroup a, Reflex t) => Semigroup (Event t a) where
   (<>) = alignWith (mergeThese (<>))
   sconcat = fmap sconcat . mergeList . toList
-#if MIN_VERSION_semigroups(0,17,0)
   stimes n = fmap $ stimes n
-#else
-  times1p n = fmap $ times1p n
-#endif
 
 instance (Semigroup a, Reflex t) => Monoid (Event t a) where
   mempty = never
@@ -1064,7 +1077,11 @@
 #endif
   align = alignEventWithMaybe Just
 
+#if defined(MIN_VERSION_semialign)
+  zip x y = mapMaybe justThese $ align x y
+#endif
 
+
 -- | Create a new 'Event' that only occurs if the supplied 'Event' occurs and
 -- the 'Behavior' is true at the time of occurrence.
 gate :: Reflex t => Behavior t Bool -> Event t a -> Event t a
@@ -1104,11 +1121,7 @@
 
 instance (Reflex t, Semigroup a) => Semigroup (Dynamic t a) where
   (<>) = zipDynWith (<>)
-#if MIN_VERSION_semigroups(0,17,0)
   stimes n = fmap $ stimes n
-#else
-  times1p n = fmap $ times1p n
-#endif
 
 instance (Reflex t, Monoid a) => Monoid (Dynamic t a) where
   mconcat = distributeListOverDynWith mconcat
diff --git a/src/Reflex/Collection.hs b/src/Reflex/Collection.hs
--- a/src/Reflex/Collection.hs
+++ b/src/Reflex/Collection.hs
@@ -27,6 +27,10 @@
   , simpleList
   ) where
 
+#if defined(MIN_VERSION_semialign)
+import Prelude hiding (zip, zipWith)
+#endif
+
 import Control.Monad.Identity
 import Data.Align
 import Data.Functor.Misc
diff --git a/src/Reflex/Dynamic/TH.hs b/src/Reflex/Dynamic/TH.hs
--- a/src/Reflex/Dynamic/TH.hs
+++ b/src/Reflex/Dynamic/TH.hs
@@ -81,7 +81,7 @@
   }
 
 mkDynExp :: String -> Q Exp
-mkDynExp s = case Hs.parseExpWithMode (Hs.defaultParseMode { Hs.extensions = [ Hs.EnableExtension Hs.TemplateHaskell ] }) s of
+mkDynExp s = case Hs.parseExpWithMode Hs.defaultParseMode { Hs.extensions = [ Hs.EnableExtension Hs.TemplateHaskell ] } s of
   Hs.ParseFailed (Hs.SrcLoc _ l c) err -> fail $ "mkDyn:" <> show l <> ":" <> show c <> ": " <> err
   Hs.ParseOk e -> qDynPure $ return $ everywhere (id `extT` reinstateUnqDyn) $ Hs.toExp $ everywhere (id `extT` antiE) e
     where TH.Name (TH.OccName occName) (TH.NameG _ _ (TH.ModName modName)) = 'unqMarker
diff --git a/src/Reflex/DynamicWriter/Class.hs b/src/Reflex/DynamicWriter/Class.hs
--- a/src/Reflex/DynamicWriter/Class.hs
+++ b/src/Reflex/DynamicWriter/Class.hs
@@ -3,7 +3,6 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE FunctionalDependencies #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE UndecidableInstances #-}
 #ifdef USE_REFLEX_OPTIMIZER
 {-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
diff --git a/src/Reflex/EventWriter/Base.hs b/src/Reflex/EventWriter/Base.hs
--- a/src/Reflex/EventWriter/Base.hs
+++ b/src/Reflex/EventWriter/Base.hs
@@ -52,7 +52,7 @@
 import Data.Semigroup
 import Data.Some (Some)
 import Data.Tuple
-import Data.Type.Equality hiding (apply)
+import Data.Type.Equality
 
 import Unsafe.Coerce
 
diff --git a/src/Reflex/EventWriter/Class.hs b/src/Reflex/EventWriter/Class.hs
--- a/src/Reflex/EventWriter/Class.hs
+++ b/src/Reflex/EventWriter/Class.hs
@@ -2,7 +2,6 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE FunctionalDependencies #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE UndecidableInstances #-}
 #ifdef USE_REFLEX_OPTIMIZER
 {-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
diff --git a/src/Reflex/Host/Class.hs b/src/Reflex/Host/Class.hs
--- a/src/Reflex/Host/Class.hs
+++ b/src/Reflex/Host/Class.hs
@@ -4,7 +4,6 @@
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE FunctionalDependencies #-}
 {-# LANGUAGE GADTs #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE RoleAnnotations #-}
 {-# LANGUAGE ScopedTypeVariables #-}
diff --git a/src/Reflex/NotReady/Class.hs b/src/Reflex/NotReady/Class.hs
--- a/src/Reflex/NotReady/Class.hs
+++ b/src/Reflex/NotReady/Class.hs
@@ -3,7 +3,6 @@
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE FunctionalDependencies #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE UndecidableInstances #-}
 #ifdef USE_REFLEX_OPTIMIZER
diff --git a/src/Reflex/Patch/IntMap.hs b/src/Reflex/Patch/IntMap.hs
--- a/src/Reflex/Patch/IntMap.hs
+++ b/src/Reflex/Patch/IntMap.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE DeriveFoldable #-}
 {-# LANGUAGE DeriveFunctor #-}
 {-# LANGUAGE DeriveTraversable #-}
@@ -33,14 +32,7 @@
 instance Semigroup (PatchIntMap v) where
   PatchIntMap a <> PatchIntMap b = PatchIntMap $ a `mappend` b --TODO: Add a semigroup instance for Map
   -- PatchMap is idempotent, so stimes n is id for every n
-#if MIN_VERSION_semigroups(0,17,0)
   stimes = stimesIdempotentMonoid
-#else
-  times1p n x = case compare n 0 of
-    LT -> error "stimesIdempotentMonoid: negative multiplier"
-    EQ -> mempty
-    GT -> x
-#endif
 
 -- | Map a function @Int -> a -> b@ over all @a@s in the given @'PatchIntMap' a@
 -- (that is, all inserts/updates), producing a @PatchIntMap b@.
diff --git a/src/Reflex/Patch/Map.hs b/src/Reflex/Patch/Map.hs
--- a/src/Reflex/Patch/Map.hs
+++ b/src/Reflex/Patch/Map.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE TypeFamilies #-}
 -- | 'Patch'es on 'Map' that consist only of insertions (including overwrites)
@@ -35,14 +34,7 @@
 instance Ord k => Semigroup (PatchMap k v) where
   PatchMap a <> PatchMap b = PatchMap $ a `mappend` b --TODO: Add a semigroup instance for Map
   -- PatchMap is idempotent, so stimes n is id for every n
-#if MIN_VERSION_semigroups(0,17,0)
   stimes = stimesIdempotentMonoid
-#else
-  times1p n x = case compare n 0 of
-    LT -> error "stimesIdempotentMonoid: negative multiplier"
-    EQ -> mempty
-    GT -> x
-#endif
 
 -- | The empty 'PatchMap' contains no insertions or deletions
 instance Ord k => Monoid (PatchMap k v) where
diff --git a/src/Reflex/PerformEvent/Base.hs b/src/Reflex/PerformEvent/Base.hs
--- a/src/Reflex/PerformEvent/Base.hs
+++ b/src/Reflex/PerformEvent/Base.hs
@@ -141,7 +141,7 @@
           case mToPerform of
             Nothing -> return [result']
             Just toPerform -> do
-              responses <- runHostFrame $ traverseRequesterData (\v -> Identity <$> v) toPerform
+              responses <- runHostFrame $ traverseRequesterData (Identity <$>) toPerform
               mrt <- readRef responseTrigger
               let followupEventTriggers = case mrt of
                     Just rt -> [rt :=> Identity responses]
diff --git a/src/Reflex/PerformEvent/Class.hs b/src/Reflex/PerformEvent/Class.hs
--- a/src/Reflex/PerformEvent/Class.hs
+++ b/src/Reflex/PerformEvent/Class.hs
@@ -5,7 +5,6 @@
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE FunctionalDependencies #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeFamilies #-}
diff --git a/src/Reflex/PostBuild/Class.hs b/src/Reflex/PostBuild/Class.hs
--- a/src/Reflex/PostBuild/Class.hs
+++ b/src/Reflex/PostBuild/Class.hs
@@ -4,7 +4,6 @@
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE FunctionalDependencies #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE TypeOperators #-}
diff --git a/src/Reflex/Profiled.hs b/src/Reflex/Profiled.hs
--- a/src/Reflex/Profiled.hs
+++ b/src/Reflex/Profiled.hs
@@ -9,6 +9,7 @@
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE UndecidableInstances #-}
 {-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE TypeApplications #-}
 {-# LANGUAGE RankNTypes #-}
 -- |
 -- Module:
@@ -79,9 +80,9 @@
           go (cc : l) parent
 
 toCostCentreTree :: Ptr CostCentreStack -> Int -> IO CostCentreTree
-toCostCentreTree ccs n = do
-  ccList <- getCostCentreStack ccs
-  return $ foldr (\cc child -> CostCentreTree 0 n $ Map.singleton cc child) (CostCentreTree n n mempty) ccList
+toCostCentreTree ccs n =
+  foldr (\cc child -> CostCentreTree 0 n $ Map.singleton cc child) (CostCentreTree n n mempty)
+    <$> getCostCentreStack ccs
 
 getCostCentreTree :: IO CostCentreTree
 getCostCentreTree = do
@@ -151,13 +152,16 @@
   currentIncremental (Incremental_Profiled i) = coerce $ currentIncremental i
   updatedIncremental (Incremental_Profiled i) = coerce $ profileEvent $ updatedIncremental i
   incrementalToDynamic (Incremental_Profiled i) = coerce $ incrementalToDynamic i
-  behaviorCoercion (c :: Coercion a b) = case behaviorCoercion c :: Coercion (Behavior t a) (Behavior t b) of
-    Coercion -> unsafeCoerce (Coercion :: Coercion (Behavior (ProfiledTimeline t) a) (Behavior (ProfiledTimeline t) a)) --TODO: Figure out how to make this typecheck without the unsafeCoerce
-  eventCoercion (c :: Coercion a b) = case eventCoercion c :: Coercion (Event t a) (Event t b) of
-    Coercion -> unsafeCoerce (Coercion :: Coercion (Event (ProfiledTimeline t) a) (Event (ProfiledTimeline t) a)) --TODO: Figure out how to make this typecheck without the unsafeCoerce
-  dynamicCoercion (c :: Coercion a b) = case dynamicCoercion c :: Coercion (Dynamic t a) (Dynamic t b) of
-    Coercion -> unsafeCoerce (Coercion :: Coercion (Dynamic (ProfiledTimeline t) a) (Dynamic (ProfiledTimeline t) a)) --TODO: Figure out how to make this typecheck without the unsafeCoerce
-  mergeIntIncremental = Event_Profiled . mergeIntIncremental . (unsafeCoerce :: Incremental (ProfiledTimeline t) (PatchIntMap (Event (ProfiledTimeline t) a)) -> Incremental t (PatchIntMap (Event t a)))
+  behaviorCoercion c =
+    Coercion `trans` behaviorCoercion @t c `trans` Coercion
+  eventCoercion c =
+    Coercion `trans` eventCoercion @t c `trans` Coercion
+  dynamicCoercion c =
+    Coercion `trans` dynamicCoercion @t c `trans` Coercion
+  incrementalCoercion c d =
+    Coercion `trans` incrementalCoercion @t c d `trans` Coercion
+  mergeIntIncremental = Event_Profiled . mergeIntIncremental .
+    coerceWith (Coercion `trans` incrementalCoercion Coercion Coercion `trans` Coercion)
   fanInt (Event_Profiled e) = coerce $ fanInt $ profileEvent e
 
 deriving instance Functor (Dynamic t) => Functor (Dynamic (ProfiledTimeline t))
diff --git a/src/Reflex/Pure.hs b/src/Reflex/Pure.hs
--- a/src/Reflex/Pure.hs
+++ b/src/Reflex/Pure.hs
@@ -31,14 +31,9 @@
   , Incremental (..)
   ) where
 
-#if !MIN_VERSION_base(4,8,0)
-import Control.Applicative
-#endif
-
 import Control.Monad
 import Data.Dependent.Map (DMap, GCompare)
 import qualified Data.Dependent.Map as DMap
-import Data.Functor.Identity
 import Data.IntMap (IntMap)
 import qualified Data.IntMap as IntMap
 import Data.Maybe
@@ -93,7 +88,8 @@
        then Nothing
        else Just currentOccurrences
 
-  -- fanG :: GCompare k => Event (Pure t) (DMap k v) -> EventSelectorG (Pure t) k v
+--  The instance signature doeesn't compile, leave commented for documentation
+--  fanG :: GCompare k => Event (Pure t) (DMap k v) -> EventSelectorG (Pure t) k v
   fanG e = EventSelectorG $ \k -> Event $ \t -> unEvent e t >>= DMap.lookup k
 
   switch :: Behavior (Pure t) (Event (Pure t) a) -> Event (Pure t) a
@@ -133,6 +129,7 @@
   behaviorCoercion Coercion = Coercion
   eventCoercion Coercion = Coercion
   dynamicCoercion Coercion = Coercion
+  incrementalCoercion Coercion Coercion = Coercion
 
   fanInt e = EventSelectorInt $ \k -> Event $ \t -> unEvent e t >>= IntMap.lookup k
 
diff --git a/src/Reflex/Query/Base.hs b/src/Reflex/Query/Base.hs
--- a/src/Reflex/Query/Base.hs
+++ b/src/Reflex/Query/Base.hs
@@ -1,7 +1,6 @@
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE InstanceSigs #-}
-{-# LANGUAGE KindSignatures #-}
 {-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE RankNTypes #-}
diff --git a/src/Reflex/Query/Class.hs b/src/Reflex/Query/Class.hs
--- a/src/Reflex/Query/Class.hs
+++ b/src/Reflex/Query/Class.hs
@@ -3,7 +3,6 @@
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE FunctionalDependencies #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE UndecidableInstances #-}
 -- |
diff --git a/src/Reflex/Requester/Class.hs b/src/Reflex/Requester/Class.hs
--- a/src/Reflex/Requester/Class.hs
+++ b/src/Reflex/Requester/Class.hs
@@ -6,7 +6,6 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE FunctionalDependencies #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE RecursiveDo #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE UndecidableInstances #-}
diff --git a/src/Reflex/Spider/Internal.hs b/src/Reflex/Spider/Internal.hs
--- a/src/Reflex/Spider/Internal.hs
+++ b/src/Reflex/Spider/Internal.hs
@@ -9,7 +9,6 @@
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE LambdaCase #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE MultiWayIf #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE RoleAnnotations #-}
@@ -18,6 +17,8 @@
 {-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE UndecidableInstances #-}
 {-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE DeriveFunctor #-}
+{-# LANGUAGE StandaloneDeriving #-}
 {-# LANGUAGE InstanceSigs #-}
 
 #ifdef USE_REFLEX_OPTIMIZER
@@ -37,7 +38,10 @@
 import Control.Monad.Exception
 import Control.Monad.Identity hiding (forM, forM_, mapM, mapM_)
 import Control.Monad.Primitive
-import Control.Monad.Reader hiding (forM, forM_, mapM, mapM_)
+--import Control.Monad.Reader hiding (forM, forM_, mapM, mapM_)
+import Control.Monad.Reader.Class
+import Control.Monad.IO.Class
+import Control.Monad.ReaderIO
 import Control.Monad.Ref
 import Data.Align
 import Data.Coerce
@@ -68,6 +72,12 @@
 import System.Mem.Weak
 import Unsafe.Coerce
 
+#if defined(MIN_VERSION_semialign)
+#if MIN_VERSION_these(0,8,0)
+import Data.These.Combinators (justThese)
+#endif
+#endif
+
 #ifdef DEBUG_CYCLES
 import Control.Monad.State hiding (forM, forM_, mapM, mapM_, sequence)
 import Data.List.NonEmpty (NonEmpty (..), nonEmpty)
@@ -545,6 +555,11 @@
 toAny :: a -> Any
 toAny = unsafeCoerce
 
+-- Why do we use Any here, instead of just giving eventSubscribedRetained an
+-- existential type? Sadly, GHC does not currently know how to unbox types
+-- with existentially quantified fields. So instead we just coerce values
+-- to type Any on the way in. Since we never coerce them back, this is
+-- perfectly safe.
 data EventSubscribed x = EventSubscribed
   { eventSubscribedHeightRef :: {-# UNPACK #-} !(IORef Height)
   , eventSubscribedRetained :: {-# NOUNPACK #-} !Any
@@ -668,7 +683,7 @@
         wi <- liftIO $ mkWeakPtrWithDebug i "InvalidatorPull"
         parentsRef <- liftIO $ newIORef []
         holdInits <- askBehaviorHoldInits
-        a <- liftIO $ runReaderT (unBehaviorM $ pullCompute p) (Just (wi, parentsRef), holdInits)
+        a <- liftIO $ runReaderIO (unBehaviorM $ pullCompute p) (Just (wi, parentsRef), holdInits)
         invsRef <- liftIO . newIORef . maybeToList =<< askInvalidator
         parents <- liftIO $ readIORef parentsRef
         let subscribed = PullSubscribed
@@ -703,42 +718,46 @@
 -- Dynamic
 --------------------------------------------------------------------------------
 
-data Dynamic x p = Dynamic
-  { dynamicCurrent :: !(Behavior x (PatchTarget p))
+type DynamicS x p = Dynamic x (PatchTarget p) p
+
+data Dynamic x target p = Dynamic
+  { dynamicCurrent :: !(Behavior x target)
   , dynamicUpdated :: Event x p -- This must be lazy; see the comment on holdEvent --TODO: Would this let us eliminate `Dyn`?
   }
 
-dynamicHold :: Hold x p -> Dynamic x p
+deriving instance (HasSpiderTimeline x) => Functor (Dynamic x target)
+
+
+
+
+dynamicHold :: Hold x p -> DynamicS x p
 dynamicHold !h = Dynamic
   { dynamicCurrent = behaviorHold h
   , dynamicUpdated = eventHold h
   }
 
-dynamicHoldIdentity :: Hold x (Identity a) -> Dynamic x (Identity a)
+dynamicHoldIdentity :: Hold x (Identity a) -> DynamicS x (Identity a)
 dynamicHoldIdentity = dynamicHold
 
-dynamicConst :: PatchTarget p -> Dynamic x p
+dynamicConst :: PatchTarget p -> DynamicS x p
 dynamicConst !a = Dynamic
   { dynamicCurrent = behaviorConst a
   , dynamicUpdated = eventNever
   }
 
-dynamicDyn :: (HasSpiderTimeline x, Patch p) => Dyn x p -> Dynamic x p
+dynamicDyn :: (HasSpiderTimeline x, Patch p) => Dyn x p -> DynamicS x p
 dynamicDyn !d = Dynamic
   { dynamicCurrent = behaviorDyn d
   , dynamicUpdated = eventDyn d
   }
 
-dynamicDynIdentity :: HasSpiderTimeline x => Dyn x (Identity a) -> Dynamic x (Identity a)
+dynamicDynIdentity :: HasSpiderTimeline x => Dyn x (Identity a) -> DynamicS x (Identity a)
 dynamicDynIdentity = dynamicDyn
 
 --------------------------------------------------------------------------------
 -- Combinators
 --------------------------------------------------------------------------------
 
---TODO: Figure out why certain things are not 'representational', then make them
---representational so we can use coerce
-
 --type role Hold representational
 data Hold x p
    = Hold { holdValue :: !(IORef (PatchTarget p))
@@ -759,20 +778,25 @@
 
 -- | Stores all global data relevant to a particular Spider timeline; only one
 -- value should exist for each type @x@
-data SpiderTimelineEnv x = SpiderTimelineEnv
+newtype SpiderTimelineEnv x = STE {unSTE :: SpiderTimelineEnv' x}
+-- We implement SpiderTimelineEnv with a newtype wrapper so
+-- we can get the coercions we want safely.
+type role SpiderTimelineEnv nominal
+
+data SpiderTimelineEnv' x = SpiderTimelineEnv
   { _spiderTimeline_lock :: {-# UNPACK #-} !(MVar ())
   , _spiderTimeline_eventEnv :: {-# UNPACK #-} !(EventEnv x)
 #ifdef DEBUG
   , _spiderTimeline_depth :: {-# UNPACK #-} !(IORef Int)
 #endif
   }
-type role SpiderTimelineEnv nominal
+type role SpiderTimelineEnv' phantom
 
 instance Eq (SpiderTimelineEnv x) where
   _ == _ = True -- Since only one exists of each type
 
 instance GEq SpiderTimelineEnv where
-  a `geq` b = if _spiderTimeline_lock a == _spiderTimeline_lock b
+  a `geq` b = if _spiderTimeline_lock (unSTE a) == _spiderTimeline_lock (unSTE b)
               then Just $ unsafeCoerce Refl -- This unsafeCoerce is safe because the same SpiderTimelineEnv can't have two different 'x' arguments
               else Nothing
 
@@ -795,7 +819,7 @@
 runEventM = unEventM
 
 asksEventEnv :: forall x a. HasSpiderTimeline x => (EventEnv x -> a) -> EventM x a
-asksEventEnv f = return $ f $ _spiderTimeline_eventEnv (spiderTimeline :: SpiderTimelineEnv x)
+asksEventEnv f = return $ f $ _spiderTimeline_eventEnv (unSTE (spiderTimeline :: SpiderTimelineEnv x))
 
 class MonadIO m => Defer a m where
   getDeferralQueue :: m (IORef [a])
@@ -933,9 +957,9 @@
 
 type BehaviorEnv x = (Maybe (Weak (Invalidator x), IORef [SomeBehaviorSubscribed x]), IORef [SomeHoldInit x])
 
---type role BehaviorM representational
 -- BehaviorM can sample behaviors
-newtype BehaviorM x a = BehaviorM { unBehaviorM :: ReaderT (BehaviorEnv x) IO a } deriving (Functor, Applicative, MonadIO, MonadFix)
+newtype BehaviorM x a = BehaviorM { unBehaviorM :: ReaderIO (BehaviorEnv x) a }
+  deriving (Functor, Applicative, MonadIO, MonadFix, MonadReader (BehaviorEnv x))
 
 instance Monad (BehaviorM x) where
   {-# INLINE (>>=) #-}
@@ -1139,17 +1163,21 @@
   align ea eb = mapMaybe dmapToThese $ mergeG coerce $ dynamicConst $
      DMap.fromDistinctAscList [LeftTag :=> ea, RightTag :=> eb]
 
+#if defined(MIN_VERSION_semialign)
+  zip x y = mapMaybe justThese $ align x y
+#endif
+
 data DynType x p = UnsafeDyn !(BehaviorM x (PatchTarget p), Event x p)
                  | BuildDyn  !(EventM x (PatchTarget p), Event x p)
                  | HoldDyn   !(Hold x p)
 
 newtype Dyn (x :: Type) p = Dyn { unDyn :: IORef (DynType x p) }
 
-newMapDyn :: HasSpiderTimeline x => (a -> b) -> Dynamic x (Identity a) -> Dynamic x (Identity b)
+newMapDyn :: HasSpiderTimeline x => (a -> b) -> DynamicS x (Identity a) -> DynamicS x (Identity b)
 newMapDyn f d = dynamicDynIdentity $ unsafeBuildDynamic (fmap f $ readBehaviorTracked $ dynamicCurrent d) (Identity . f . runIdentity <$> dynamicUpdated d)
 
 --TODO: Avoid the duplication between this and R.zipDynWith
-zipDynWith :: HasSpiderTimeline x => (a -> b -> c) -> Dynamic x (Identity a) -> Dynamic x (Identity b) -> Dynamic x (Identity c)
+zipDynWith :: HasSpiderTimeline x => (a -> b -> c) -> DynamicS x (Identity a) -> DynamicS x (Identity b) -> DynamicS x (Identity c)
 zipDynWith f da db =
   let eab = align (dynamicUpdated da) (dynamicUpdated db)
       ec = flip push eab $ \o -> do
@@ -1225,7 +1253,7 @@
 run roots after = do
   tracePropagate (Proxy :: Proxy x) $ "Running an event frame with " <> show (length roots) <> " events"
   let t = spiderTimeline :: SpiderTimelineEnv x
-  result <- SpiderHost $ withMVar (_spiderTimeline_lock t) $ \_ -> unSpiderHost $ runFrame $ do
+  result <- SpiderHost $ withMVar (_spiderTimeline_lock (unSTE t)) $ \_ -> unSpiderHost $ runFrame $ do
     rootsToPropagate <- forM roots $ \r@(RootTrigger (_, occRef, k) :=> a) -> do
       occBefore <- liftIO $ do
         occBefore <- readIORef occRef
@@ -1289,9 +1317,9 @@
 withIncreasedDepth :: CanTrace x m => m a -> m a
 withIncreasedDepth a = do
   spiderTimeline <- askSpiderTimelineEnv
-  liftIO $ modifyIORef' (_spiderTimeline_depth spiderTimeline) succ
+  liftIO $ modifyIORef' (_spiderTimeline_depth (unSTE spiderTimeline)) succ
   result <- a
-  liftIO $ modifyIORef' (_spiderTimeline_depth spiderTimeline) pred
+  liftIO $ modifyIORef' (_spiderTimeline_depth (unSTE spiderTimeline)) pred
   return result
 #else
 withIncreasedDepth :: m a -> m a
@@ -1318,7 +1346,7 @@
   message <- getMessage
 #ifdef DEBUG
   spiderTimeline <- askSpiderTimelineEnv
-  d <- liftIO $ readIORef $ _spiderTimeline_depth spiderTimeline
+  d <- liftIO $ readIORef $ _spiderTimeline_depth $ unSTE spiderTimeline
 #else
   let d = 0
 #endif
@@ -1359,25 +1387,25 @@
 data SomeResetCoincidence x = forall a. SomeResetCoincidence !(EventSubscription x) !(Maybe (CoincidenceSubscribed x a)) -- The CoincidenceSubscriber will be present only if heights need to be reset
 
 runBehaviorM :: BehaviorM x a -> Maybe (Weak (Invalidator x), IORef [SomeBehaviorSubscribed x]) -> IORef [SomeHoldInit x] -> IO a
-runBehaviorM a mwi holdInits = runReaderT (unBehaviorM a) (mwi, holdInits)
+runBehaviorM a mwi holdInits = runReaderIO (unBehaviorM a) (mwi, holdInits)
 
 askInvalidator :: BehaviorM x (Maybe (Weak (Invalidator x)))
 askInvalidator = do
-  (!m, _) <- BehaviorM ask
+  (!m, _) <- ask
   case m of
     Nothing -> return Nothing
     Just (!wi, _) -> return $ Just wi
 
 askParentsRef :: BehaviorM x (Maybe (IORef [SomeBehaviorSubscribed x]))
 askParentsRef = do
-  (!m, _) <- BehaviorM ask
+  (!m, _) <- ask
   case m of
     Nothing -> return Nothing
     Just (_, !p) -> return $ Just p
 
 askBehaviorHoldInits :: BehaviorM x (IORef [SomeHoldInit x])
 askBehaviorHoldInits = do
-  (_, !his) <- BehaviorM ask
+  (_, !his) <- ask
   return his
 
 {-# INLINE getDynHold #-}
@@ -1701,20 +1729,20 @@
 {-# INLINE mergeG #-}
 mergeG :: forall k q x v. (HasSpiderTimeline x, GCompare k)
   => (forall a. q a -> Event x (v a))
-  -> Dynamic x (PatchDMap k q) -> Event x (DMap k v)
+  -> DynamicS x (PatchDMap k q) -> Event x (DMap k v)
 mergeG nt d = cacheEvent (mergeCheap nt d)
 
 {-# INLINE mergeWithMove #-}
 mergeWithMove :: forall k v q x. (HasSpiderTimeline x, GCompare k)
   => (forall a. q a -> Event x (v a))
-  -> Dynamic x (PatchDMapWithMove k q) -> Event x (DMap k v)
+  -> DynamicS x (PatchDMapWithMove k q) -> Event x (DMap k v)
 mergeWithMove nt d = cacheEvent (mergeCheapWithMove nt d)
 
 {-# INLINE [1] mergeCheap #-}
 mergeCheap
   :: forall k x q v. (HasSpiderTimeline x, GCompare k)
   => (forall a. q a -> Event x (v a))
-  -> Dynamic x (PatchDMap k q)
+  -> DynamicS x (PatchDMap k q)
   -> Event x (DMap k v)
 mergeCheap nt = mergeGCheap' getInitialSubscribers updateMe destroy
   where
@@ -1742,7 +1770,7 @@
           let s = subscriber $ return k
           (subscription@(EventSubscription _ parentSubd), parentOcc) <- subscribeAndRead (nt e) s
           height <- liftIO $ getEventSubscribedHeight parentSubd
-          return (fmap (\x -> k :=> x) parentOcc, height, k :=> MergeSubscribedParent subscription)
+          return (fmap (k :=>) parentOcc, height, k :=> MergeSubscribedParent subscription)
         return ( DMap.fromDistinctAscList $ mapMaybe (\(x, _, _) -> x) subscribers
                , fmap (\(_, h, _) -> h) subscribers --TODO: Assert that there's no invalidHeight in here
                , DMap.fromDistinctAscList $ map (\(_, _, x) -> x) subscribers
@@ -1754,7 +1782,7 @@
 {-# INLINE [1] mergeCheapWithMove #-}
 mergeCheapWithMove :: forall k x v q. (HasSpiderTimeline x, GCompare k)
   => (forall a. q a -> Event x (v a))
-  -> Dynamic x (PatchDMapWithMove k q)
+  -> DynamicS x (PatchDMapWithMove k q)
   -> Event x (DMap k v)
 mergeCheapWithMove nt = mergeGCheap' getInitialSubscribers updateMe destroy
   where
@@ -1790,7 +1818,7 @@
           let s = subscriber $ liftIO $ readIORef keyRef
           (subscription@(EventSubscription _ parentSubd), parentOcc) <- subscribeAndRead (nt e) s
           height <- liftIO $ getEventSubscribedHeight parentSubd
-          return (fmap (\x -> k :=> x) parentOcc, height, k :=> MergeSubscribedParentWithMove subscription keyRef)
+          return (fmap (k :=>) parentOcc, height, k :=> MergeSubscribedParentWithMove subscription keyRef)
         return ( DMap.fromDistinctAscList $ mapMaybe (\(x, _, _) -> x) subscribers
                , fmap (\(_, h, _) -> h) subscribers --TODO: Assert that there's no invalidHeight in here
                , DMap.fromDistinctAscList $ map (\(_, _, x) -> x) subscribers
@@ -1902,7 +1930,7 @@
 
 {-# INLINE mergeGCheap' #-}
 mergeGCheap' :: forall k v x p s q. (HasSpiderTimeline x, GCompare k, PatchTarget p ~ DMap k q)
-  => MergeInitFunc k v q x s -> MergeUpdateFunc k v x p s -> MergeDestroyFunc k s -> Dynamic x p -> Event x (DMap k v)
+  => MergeInitFunc k v q x s -> MergeUpdateFunc k v x p s -> MergeDestroyFunc k s -> DynamicS x p -> Event x (DMap k v)
 mergeGCheap' getInitialSubscribers updateFunc destroy d = Event $ \sub -> do
   initialParents <- readBehaviorUntracked $ dynamicCurrent d
   accumRef <- liftIO $ newIORef $ error "merge: accumRef not yet initialized"
@@ -1951,11 +1979,11 @@
          , occ
          )
 
-mergeInt :: forall x a. (HasSpiderTimeline x) => Dynamic x (PatchIntMap (Event x a)) -> Event x (IntMap a)
+mergeInt :: forall x a. (HasSpiderTimeline x) => DynamicS x (PatchIntMap (Event x a)) -> Event x (IntMap a)
 mergeInt = cacheEvent . mergeIntCheap
 
 {-# INLINABLE mergeIntCheap #-}
-mergeIntCheap :: forall x a. (HasSpiderTimeline x) => Dynamic x (PatchIntMap (Event x a)) -> Event x (IntMap a)
+mergeIntCheap :: forall x a. (HasSpiderTimeline x) => DynamicS x (PatchIntMap (Event x a)) -> Event x (IntMap a)
 mergeIntCheap d = Event $ \sub -> do
   initialParents <- readBehaviorUntracked $ dynamicCurrent d
   accum <- liftIO $ FastMutableIntMap.newEmpty
@@ -2115,7 +2143,7 @@
 -- | Run an event action outside of a frame
 runFrame :: forall x a. HasSpiderTimeline x => EventM x a -> SpiderHost x a --TODO: This function also needs to hold the mutex
 runFrame a = SpiderHost $ do
-  let env = _spiderTimeline_eventEnv (spiderTimeline :: SpiderTimelineEnv x)
+  let env = _spiderTimeline_eventEnv $ unSTE (spiderTimeline :: SpiderTimelineEnv x)
   let go = do
         result <- a
         runHoldInits (eventEnvHoldInits env) (eventEnvDynInits env) (eventEnvMergeInits env) -- This must happen before doing the assignments, in case subscribing a Hold causes existing Holds to be read by the newly-propagated events
@@ -2326,7 +2354,7 @@
   fail _ = error "Dynamic does not support 'fail'"
 
 {-# INLINABLE newJoinDyn #-}
-newJoinDyn :: HasSpiderTimeline x => Reflex.Spider.Internal.Dynamic x (Identity (Reflex.Spider.Internal.Dynamic x (Identity a))) -> Reflex.Spider.Internal.Dyn x (Identity a)
+newJoinDyn :: HasSpiderTimeline x => DynamicS x (Identity (DynamicS x (Identity a))) -> Reflex.Spider.Internal.Dyn x (Identity a)
 newJoinDyn d =
   let readV0 = readBehaviorTracked . dynamicCurrent =<< readBehaviorTracked (dynamicCurrent d)
       eOuter = Reflex.Spider.Internal.push (fmap (Just . Identity) . readBehaviorUntracked . dynamicCurrent . runIdentity) $ dynamicUpdated d
@@ -2476,7 +2504,7 @@
 #ifdef DEBUG
   depthRef <- newIORef 0
 #endif
-  return $ SpiderTimelineEnv
+  return $ STE $ SpiderTimelineEnv
     { _spiderTimeline_lock = lock
     , _spiderTimeline_eventEnv = env
 #ifdef DEBUG
@@ -2492,13 +2520,13 @@
 
 instance Reifies s (SpiderTimelineEnv x) =>
          HasSpiderTimeline (LocalSpiderTimeline x s) where
-  spiderTimeline = localSpiderTimeline (Proxy :: Proxy s) $ reflect (Proxy :: Proxy s)
+  spiderTimeline = localSpiderTimeline Proxy $ reflect (Proxy :: Proxy s)
 
 localSpiderTimeline
-  :: Proxy s
+  :: proxy s
   -> SpiderTimelineEnv x
   -> SpiderTimelineEnv (LocalSpiderTimeline x s)
-localSpiderTimeline _ = unsafeCoerce
+localSpiderTimeline _ = coerce
 
 -- | Pass a new timeline to the given function.
 withSpiderTimeline :: (forall x. HasSpiderTimeline x => SpiderTimelineEnv x -> IO r) -> IO r
@@ -2516,8 +2544,8 @@
   {-# SPECIALIZE instance R.Reflex (SpiderTimeline Global) #-}
   newtype Behavior (SpiderTimeline x) a = SpiderBehavior { unSpiderBehavior :: Behavior x a }
   newtype Event (SpiderTimeline x) a = SpiderEvent { unSpiderEvent :: Event x a }
-  newtype Dynamic (SpiderTimeline x) a = SpiderDynamic { unSpiderDynamic :: Dynamic x (Identity a) } -- deriving (Functor, Applicative, Monad)
-  newtype Incremental (SpiderTimeline x) p = SpiderIncremental { unSpiderIncremental :: Dynamic x p }
+  newtype Dynamic (SpiderTimeline x) a = SpiderDynamic { unSpiderDynamic :: DynamicS x (Identity a) } -- deriving (Functor, Applicative, Monad)
+  newtype Incremental (SpiderTimeline x) p = SpiderIncremental { unSpiderIncremental :: DynamicS x p }
   type PullM (SpiderTimeline x) = SpiderPullM x
   type PushM (SpiderTimeline x) = SpiderPushM x
   {-# INLINABLE never #-}
@@ -2546,7 +2574,7 @@
   {-# INLINABLE current #-}
   current = SpiderBehavior . dynamicCurrent . unSpiderDynamic
   {-# INLINABLE updated #-}
-  updated = coerce $ SpiderEvent . dynamicUpdated . unSpiderDynamic
+  updated = SpiderEvent #. dynamicUpdated .# fmap coerce . unSpiderDynamic
   {-# INLINABLE unsafeBuildDynamic #-}
   unsafeBuildDynamic readV0 v' = SpiderDynamic $ dynamicDynIdentity $ unsafeBuildDynamic (coerce readV0) $ coerce $ unSpiderEvent v'
   {-# INLINABLE unsafeBuildIncremental #-}
@@ -2565,9 +2593,10 @@
     return $ Identity <$> apply p c --TODO: Avoid the redundant 'apply'
   eventCoercion Coercion = Coercion
   behaviorCoercion Coercion = Coercion
-  dynamicCoercion = unsafeCoerce --TODO: How can we avoid this unsafeCoerce?  This is safe only because we know how Identity works as a Patch instance
+  dynamicCoercion Coercion = Coercion
+  incrementalCoercion Coercion Coercion = Coercion
   {-# INLINABLE mergeIntIncremental #-}
-  mergeIntIncremental = SpiderEvent . mergeInt . (unsafeCoerce :: Dynamic x (PatchIntMap (R.Event (SpiderTimeline x) a)) -> Dynamic x (PatchIntMap (Event x a))) . unSpiderIncremental
+  mergeIntIncremental = SpiderEvent . mergeInt . coerce
   {-# INLINABLE fanInt #-}
   fanInt e = R.EventSelectorInt $ SpiderEvent . selectInt (fanInt (unSpiderEvent e))
 
diff --git a/src/Reflex/TriggerEvent/Class.hs b/src/Reflex/TriggerEvent/Class.hs
--- a/src/Reflex/TriggerEvent/Class.hs
+++ b/src/Reflex/TriggerEvent/Class.hs
@@ -2,7 +2,6 @@
 -- new 'Event's that can be triggered from 'IO'.
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE FunctionalDependencies #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE UndecidableInstances #-}
 module Reflex.TriggerEvent.Class
   ( TriggerEvent (..)
diff --git a/test/EventWriterT.hs b/test/EventWriterT.hs
--- a/test/EventWriterT.hs
+++ b/test/EventWriterT.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE BangPatterns #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE GADTs #-}
@@ -13,6 +14,10 @@
 import qualified Data.Map as M
 import Data.These
 
+#if defined(MIN_VERSION_these_lens) || (MIN_VERSION_these(0,8,0) && !MIN_VERSION_these(0,9,0))
+import Data.These.Lens
+#endif
+
 import Reflex
 import Reflex.EventWriter.Base
 import Test.Run
@@ -48,16 +53,13 @@
   return e
 
 testOrdering :: (Reflex t, Monad m) => Event t () -> EventWriterT t [Int] m ()
-testOrdering pulse = do
-  forM_ [10,9..1] $ \i -> tellEvent ([i] <$ pulse)
-  return ()
+testOrdering pulse = forM_ [10,9..1] $ \i -> tellEvent ([i] <$ pulse)
 
 testSimultaneous :: (Reflex t, Adjustable t m, MonadHold t m) => Event t (These () ()) -> EventWriterT t [Int] m ()
 testSimultaneous pulse = do
   let e0 = fmapMaybe (^? here) pulse
       e1 = fmapMaybe (^? there) pulse
   forM_ [1,3..9] $ \i -> runWithReplace (tellEvent ([i] <$ e0)) $ ffor e1 $ \_ -> tellEvent ([i+1] <$ e0)
-  return ()
 
 -- | Test that a widget telling and event which fires at the same time it has been replaced
 -- doesn't count along with the new widget.
diff --git a/test/QueryT.hs b/test/QueryT.hs
--- a/test/QueryT.hs
+++ b/test/QueryT.hs
@@ -19,6 +19,10 @@
 import Data.Semigroup
 import Data.These
 
+#if defined(MIN_VERSION_these_lens) || (MIN_VERSION_these(0,8,0) && !MIN_VERSION_these(0,9,0))
+import Data.These.Lens
+#endif
+
 import Reflex
 import Reflex.Patch.MapWithMove
 import Test.Run
diff --git a/test/Reflex/Bench/Focused.hs b/test/Reflex/Bench/Focused.hs
--- a/test/Reflex/Bench/Focused.hs
+++ b/test/Reflex/Bench/Focused.hs
@@ -130,6 +130,16 @@
 joinDynChain :: (Reflex t, MonadHold t m) => Word -> Dynamic t Word -> m (Dynamic t Word)
 joinDynChain = iterM (\d -> return $ join $ fmap (const d) d)
 
+holdDynChain :: (Reflex t, MonadHold t m) => Word -> Dynamic t Word -> m (Dynamic t Word)
+holdDynChain = iterM (\d -> sample (current d) >>= flip holdDyn (updated d))
+
+buildDynChain :: (Reflex t, MonadHold t m) => Word -> Dynamic t Word -> m (Dynamic t Word)
+buildDynChain = iterM (\d -> do 
+    let b = fmap (+1) (current d)
+        e = fmap (*2) (updated d)
+    buildDynamic (sample b) e)
+
+
 combineDynChain :: (Reflex t, MonadHold t m) => Word -> Dynamic t Word -> m (Dynamic t Word)
 combineDynChain = iterM (\d -> return $ zipDynWith (+) d d)
 
@@ -308,6 +318,8 @@
 dynamics n =
   [ testE "mapDynChain"         $ fmap updated $ mapDynChain n =<< d
   , testE "joinDynChain"        $ fmap updated $ joinDynChain n =<< d
+  , testE "holdDynChain"        $ fmap updated $ holdDynChain n =<< d
+  , testE "buildDynChain"        $ fmap updated $ buildDynChain n =<< d
   , testE "combineDynChain"     $ fmap updated $ combineDynChain n =<< d
   , testE "dense mergeTree"     $ fmap (updated . mergeTreeDyn 8) dense
   , testE "sparse mergeTree"    $ fmap (updated . mergeTreeDyn 8) sparse
diff --git a/test/Reflex/Test/CrossImpl.hs b/test/Reflex/Test/CrossImpl.hs
--- a/test/Reflex/Test/CrossImpl.hs
+++ b/test/Reflex/Test/CrossImpl.hs
@@ -218,6 +218,11 @@
        bb <- hold b $ pushAlways (const $ hold "asdf" eo) eo
        let b' = pull $ sample =<< sample bb
        return (b', e)
+  , (,) "foldDynWhileFiring" $ TestCase (Map.singleton 0 "zxc", Map.fromList [(1, "qwer"), (2, "lkj")]) $ \(_, e) -> do
+       d <- foldDyn (:) [] $
+         pushAlways (\a -> foldDyn (:) [a] e) e
+       let b = current (join (fmap distributeListOverDynPure d))
+       return (b, e)
   , (,) "joinDyn" $ TestCase (Map.singleton 0 (0 :: Int), Map.fromList [(1, "qwer"), (2, "lkj")]) $ \(b, e) -> do
        bb <- hold "b" e
        bd <- hold never . fmap (const e) =<< headE e
diff --git a/test/RequesterT.hs b/test/RequesterT.hs
--- a/test/RequesterT.hs
+++ b/test/RequesterT.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE BangPatterns #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE GADTs #-}
@@ -14,6 +15,10 @@
 import Data.Functor.Misc
 import qualified Data.Map as M
 import Data.These
+
+#if defined(MIN_VERSION_these_lens) || (MIN_VERSION_these(0,8,0) && !MIN_VERSION_these(0,9,0))
+import Data.These.Lens
+#endif
 
 import Reflex
 import Reflex.Requester.Base
diff --git a/test/hlint.hs b/test/hlint.hs
--- a/test/hlint.hs
+++ b/test/hlint.hs
@@ -22,6 +22,7 @@
         , "--ignore=Use unless"
         , "--ignore=Reduce duplication"
         , "--cpp-define=USE_TEMPLATE_HASKELL"
+        , "--ignore=Use tuple-section"
         ]
       recurseInto = and <$> sequence
         [ fileType ==? Directory
