diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,8 @@
 # Revision history for reflex-dom-core
 
+## 0.8.1.1
+* Support GHC 9.10
+
 ## 0.8.1.0
 
 * Add functions for managing history (popHistoryState and manageHistoryExposingExternalUpdates)
diff --git a/reflex-dom-core.cabal b/reflex-dom-core.cabal
--- a/reflex-dom-core.cabal
+++ b/reflex-dom-core.cabal
@@ -1,6 +1,6 @@
 cabal-version: 1.24
 Name: reflex-dom-core
-Version: 0.8.1.0
+Version: 0.8.1.1
 Synopsis: Functional Reactive Web Apps with Reflex
 Description:
   Web applications without callbacks or side-effects.
@@ -64,61 +64,66 @@
   default: True
   manual: True
 
+flag hlint-tests
+  description: Whether to run the hlint tests
+  default: False
+  manual: True
+
 library
   hs-source-dirs: src
   build-depends:
-    aeson >= 0.8 && < 2.2,
-    base >= 4.7 && < 4.15,
+    aeson >= 0.8 && < 2.3,
+    base >= 4.7 && < 4.21,
     bifunctors >= 4.2 && < 6,
-    bimap >= 0.3 && < 0.5,
+    bimap >= 0.3 && < 0.6,
     blaze-builder >= 0.4.1 && < 0.5,
-    bytestring == 0.10.*,
+    bytestring >= 0.10 && < 0.13,
     case-insensitive < 1.3,
-    commutative-semigroups >=0.1 && <0.2,
-    containers >= 0.6 && < 0.7,
-    constraints >= 0.9 && < 0.14,
+    commutative-semigroups >=0.1 && <0.3,
+    containers >= 0.6 && < 0.8,
+    constraints >= 0.9 && < 0.15,
     contravariant >= 1.4 && < 1.6,
-    data-default >= 0.5 && < 0.8,
+    data-default >= 0.5 && < 0.9,
     dependent-map >= 0.3 && < 0.5,
     dependent-sum >= 0.6 && < 0.8,
-    dependent-sum-template >= 0.1 && < 0.2,
+    dependent-sum-template >= 0.1 && < 0.3,
     directory >= 1.2 && < 1.4,
     exception-transformers == 0.4.*,
     ghcjs-dom >= 0.9.1.0 && < 0.10,
     jsaddle >= 0.9.0.0 && < 0.10,
     -- keycode-0.2 has a bug on firefox
     keycode >= 0.2.1 && < 0.3,
-    lens >= 4.7 && < 5.3,
+    lens >= 4.7 && < 5.4,
     monad-control >= 1.0.1 && < 1.1,
-    mtl >= 2.1 && < 2.3,
-    primitive >= 0.5 && < 0.8,
-    random >= 1.1 && < 1.3,
+    mtl >= 2.1 && < 2.4,
+    primitive >= 0.5 && < 0.10,
+    random >= 1.1 && < 1.4,
     ref-tf >= 0.4 && < 0.6,
     reflex >= 0.8.2.1 && < 1,
-    semigroups >= 0.16 && < 0.20,
+    semigroups >= 0.16 && < 0.21,
     stm >= 2.4 && < 2.6,
-    text == 1.2.*,
-    transformers >= 0.3 && < 0.6,
+    text >= 1.2 && < 2.2,
+    transformers >= 0.3 && < 0.7,
     network-uri >= 2.6.1 && < 2.7,
     zenc == 0.1.*
 
-  if impl(ghcjs)
+  if impl(ghcjs) || arch(javascript)
     hs-source-dirs: src-ghcjs
     build-depends:
       ghcjs-base,
-      hashable >= 1.2 && < 1.4
+      hashable >= 1.2 && < 1.5
   else
     hs-source-dirs: src-ghc
     if !os(windows)
-      build-depends: unix == 2.7.*
+      build-depends: unix >= 2.7 && <2.9
 
   if flag(split-these)
     build-depends:
-      semialign >= 1 && < 1.3,
+      semialign >= 1 && < 1.4,
       these >= 1 && < 1.3
   else
     build-depends:
-      these >= 0.4 && < 0.9
+      these >= 0.4 && < 1.0
 
   exposed-modules:
     Foreign.JavaScript.TH
@@ -169,8 +174,8 @@
 
   if flag(use-template-haskell)
     build-depends:
-      dependent-sum-template >= 0.1 && < 0.2,
-      template-haskell >= 2.12.0 && < 2.17
+      dependent-sum-template >= 0.1 && < 0.3,
+      template-haskell >= 2.12.0 && < 2.23
     other-extensions: TemplateHaskell
     cpp-options: -DUSE_TEMPLATE_HASKELL
     other-modules:
@@ -179,11 +184,14 @@
 test-suite hlint
   build-depends:
     base,
-    hlint >= 2.0 && < 4.0
+    hlint >= 2.0 && < 4.0,
+    reflex-dom-core
   hs-source-dirs: test
   main-is: hlint.hs
   type: exitcode-stdio-1.0
   default-language: Haskell98
+  if !flag(hlint-tests)
+    buildable: False
 
 test-suite hydration
   build-depends: base
@@ -226,7 +234,7 @@
                , websockets
                , which
   hs-source-dirs: test
-  ghc-options: -rtsopts -with-rtsopts=-T -Wall -fwarn-tabs -funbox-strict-fields -O2 -ferror-spans
+  ghc-options: -rtsopts "-with-rtsopts=-T -V0" -Wall -fwarn-tabs -funbox-strict-fields -O2 -ferror-spans
   ghc-prof-options: -fprof-auto -optP-DPROFILING
   main-is: hydration.hs
   type: exitcode-stdio-1.0
diff --git a/src-ghcjs/Foreign/JavaScript/Internal/Utils.hs b/src-ghcjs/Foreign/JavaScript/Internal/Utils.hs
--- a/src-ghcjs/Foreign/JavaScript/Internal/Utils.hs
+++ b/src-ghcjs/Foreign/JavaScript/Internal/Utils.hs
@@ -1,5 +1,8 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE ForeignFunctionInterface #-}
+#ifdef __ghcjs_HOST_OS
 {-# LANGUAGE JavaScriptFFI #-}
+#endif
 
 module Foreign.JavaScript.Internal.Utils
   ( synchronously
@@ -9,7 +12,11 @@
 
 import GHCJS.Concurrent
 import GHCJS.DOM.Types (JSM, JSVal, RequestAnimationFrameCallback (..))
+#if __GLASGOW_HASKELL__ < 900
 import GHCJS.Foreign.Callback (releaseCallback)
+#else
+import GHC.JS.Foreign.Callback (releaseCallback)
+#endif
 
 freeRequestAnimationFrameCallback :: RequestAnimationFrameCallback -> JSM ()
 freeRequestAnimationFrameCallback (RequestAnimationFrameCallback cb) = releaseCallback cb
diff --git a/src/Foreign/JavaScript/TH.hs b/src/Foreign/JavaScript/TH.hs
--- a/src/Foreign/JavaScript/TH.hs
+++ b/src/Foreign/JavaScript/TH.hs
@@ -35,8 +35,12 @@
 import GHCJS.DOM.Types (MonadJSM)
 import qualified GHCJS.DOM.Types as JS
 import qualified GHCJS.Foreign as JS
+#if __GLASGOW_HASKELL__ < 900
 import qualified GHCJS.Foreign.Callback as JS
 import qualified GHCJS.Foreign.Callback.Internal (Callback (..))
+#else
+import qualified GHC.JS.Foreign.Callback as JS
+#endif
 import qualified JavaScript.Array as JS
 import qualified JavaScript.Array.Internal (SomeJSArray (..))
 import qualified JavaScript.Object as JS
diff --git a/src/Reflex/Dom/Builder/Class.hs b/src/Reflex/Dom/Builder/Class.hs
--- a/src/Reflex/Dom/Builder/Class.hs
+++ b/src/Reflex/Dom/Builder/Class.hs
@@ -22,6 +22,7 @@
 {-# LANGUAGE TemplateHaskell #-}
 #endif
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE UndecidableInstances #-}
 module Reflex.Dom.Builder.Class
        ( module Reflex.Dom.Builder.Class
@@ -47,17 +48,18 @@
 
 import qualified Control.Category
 import Control.Lens hiding (element)
+import Control.Monad.Fix
 import Control.Monad.Reader
 import qualified Control.Monad.State as Lazy
 import Control.Monad.State.Strict
 import Control.Monad.Trans.Control
 import Data.Default
 import Data.Functor.Misc
+import Data.Kind (Type)
 import Data.Map (Map)
 import qualified Data.Map as Map
 import Data.Maybe
 import Data.Proxy
-import Data.Semigroup
 import Data.Semigroup.Commutative
 import Data.String
 import Data.Text (Text)
@@ -66,20 +68,20 @@
 import qualified GHCJS.DOM.Types as DOM
 
 class Default (EventSpec d EventResult) => DomSpace d where
-  type EventSpec d :: (EventTag -> *) -> *
-  type RawDocument d :: *
-  type RawTextNode d :: *
-  type RawCommentNode d :: *
-  type RawElement d :: *
-  type RawInputElement d :: *
-  type RawTextAreaElement d :: *
-  type RawSelectElement d :: *
+  type EventSpec d :: (EventTag -> Type) -> Type
+  type RawDocument d :: Type
+  type RawTextNode d :: Type
+  type RawCommentNode d :: Type
+  type RawElement d :: Type
+  type RawInputElement d :: Type
+  type RawTextAreaElement d :: Type
+  type RawSelectElement d :: Type
   addEventSpecFlags :: proxy d -> EventName en -> (Maybe (er en) -> EventFlags) -> EventSpec d er -> EventSpec d er
 
 -- | @'DomBuilder' t m@ indicates that @m@ is a 'Monad' capable of building
 -- dynamic DOM in the 'Reflex' timeline @t@
 class (Monad m, Reflex t, DomSpace (DomBuilderSpace m), NotReady t m, Adjustable t m) => DomBuilder t m | m -> t where
-  type DomBuilderSpace m :: *
+  type DomBuilderSpace m :: Type
   textNode :: TextNodeConfig t -> m (TextNode (DomBuilderSpace m) t)
   default textNode :: ( MonadTrans f
                       , m ~ f m'
@@ -159,7 +161,7 @@
   {-# INLINABLE wrapRawElement #-}
 
 class DomBuilder t m => MountableDomBuilder t m where
-  type DomFragment m :: *
+  type DomFragment m :: Type
   buildDomFragment :: m a -> m (DomFragment m, a)
   mountDomFragment :: DomFragment m -> Event t (DomFragment m) -> m ()
 
@@ -307,6 +309,15 @@
 {-# INLINE inputElementConfig_elementConfig #-}
 #endif
 
+instance (Reflex t, er ~ EventResult, DomSpace s) => Default (ElementConfig er t s) where
+  {-# INLINABLE def #-}
+  def = ElementConfig
+    { _elementConfig_namespace = Nothing
+    , _elementConfig_initialAttributes = mempty
+    , _elementConfig_modifyAttributes = Nothing
+    , _elementConfig_eventSpec = def
+    }
+
 instance (Reflex t, er ~ EventResult, DomSpace s) => Default (InputElementConfig er t s) where
   {-# INLINABLE def #-}
   def = InputElementConfig
@@ -542,15 +553,6 @@
   {-# INLINABLE namespace #-}
   namespace = elementConfig_namespace
 
-instance (Reflex t, er ~ EventResult, DomSpace s) => Default (ElementConfig er t s) where
-  {-# INLINABLE def #-}
-  def = ElementConfig
-    { _elementConfig_namespace = Nothing
-    , _elementConfig_initialAttributes = mempty
-    , _elementConfig_modifyAttributes = Nothing
-    , _elementConfig_eventSpec = def
-    }
-
 instance (DomBuilder t m, PerformEvent t m, MonadFix m, MonadHold t m) => DomBuilder t (PostBuildT t m) where
   type DomBuilderSpace (PostBuildT t m) = DomBuilderSpace m
   wrapRawElement e = lift . wrapRawElement e
@@ -641,7 +643,7 @@
 -- * Convenience functions
 
 class HasDomEvent t target eventName | target -> t where
-  type DomEventType target eventName :: *
+  type DomEventType target eventName :: Type
   domEvent :: EventName eventName -> target -> Event t (DomEventType target eventName)
 
 instance Reflex t => HasDomEvent t (Element EventResult d t) en where
@@ -748,9 +750,9 @@
 instance HasDocument m => HasDocument (QueryT t q m)
 
 class HasSetValue a where
-  type SetValue a :: *
+  type SetValue a :: Type
   setValue :: Lens' a (SetValue a)
-  
+
 instance Reflex t => HasSetValue (TextAreaElementConfig er t m) where
   type SetValue (TextAreaElementConfig er t m) = Event t Text
   setValue = textAreaElementConfig_setValue
diff --git a/src/Reflex/Dom/Builder/Class/Events.hs b/src/Reflex/Dom/Builder/Class/Events.hs
--- a/src/Reflex/Dom/Builder/Class/Events.hs
+++ b/src/Reflex/Dom/Builder/Class/Events.hs
@@ -15,6 +15,7 @@
 import Data.GADT.Compare
        (GOrdering(..), GEq(..), GCompare(..))
 #endif
+import Data.Kind (Type)
 import Data.Text (Text)
 
 data EventTag
@@ -65,7 +66,7 @@
    | TouchendTag
    | TouchcancelTag
 
-data EventName :: EventTag -> * where
+data EventName :: EventTag -> Type where
   Abort :: EventName 'AbortTag
   Blur :: EventName 'BlurTag
   Change :: EventName 'ChangeTag
@@ -115,7 +116,7 @@
 
 newtype EventResult en = EventResult { unEventResult :: EventResultType en }
 
-type family EventResultType (en :: EventTag) :: * where
+type family EventResultType (en :: EventTag) :: Type where
   EventResultType 'ClickTag = ()
   EventResultType 'DblclickTag = (Int, Int)
   EventResultType 'KeypressTag = Word
diff --git a/src/Reflex/Dom/Builder/Hydratable.hs b/src/Reflex/Dom/Builder/Hydratable.hs
--- a/src/Reflex/Dom/Builder/Hydratable.hs
+++ b/src/Reflex/Dom/Builder/Hydratable.hs
@@ -20,7 +20,7 @@
 #endif
 import Reflex
 import Reflex.Dom.Builder.Class
-import Reflex.Dom.Builder.Immediate (HasDocument (..), hydratableAttribute)
+import Reflex.Dom.Builder.Immediate (hydratableAttribute)
 import Reflex.Host.Class
 
 -- | A DomBuilder transformer that adds an attribute to all elements such that the
diff --git a/src/Reflex/Dom/Builder/Immediate.hs b/src/Reflex/Dom/Builder/Immediate.hs
--- a/src/Reflex/Dom/Builder/Immediate.hs
+++ b/src/Reflex/Dom/Builder/Immediate.hs
@@ -120,7 +120,9 @@
 import Control.Concurrent
 import Control.Exception (bracketOnError)
 import Control.Lens (Identity(..), imapM_, iforM_, (^.), makeLenses)
+import Control.Monad
 import Control.Monad.Exception
+import Control.Monad.Fix
 import Control.Monad.Primitive
 import Control.Monad.Reader
 import Control.Monad.Ref
@@ -129,7 +131,6 @@
 import Data.Default
 import Data.Dependent.Map (DMap)
 import Data.Dependent.Sum
-import Data.FastMutableIntMap (PatchIntMap (..))
 import Data.Foldable (for_, traverse_)
 import Data.Functor.Compose
 import Data.Functor.Constant
@@ -138,8 +139,8 @@
 import Data.GADT.Compare (GCompare)
 import Data.IORef
 import Data.IntMap.Strict (IntMap)
+import Data.Kind (Type)
 import Data.Maybe
-import Data.Monoid ((<>))
 import Data.Some (Some(..))
 import Data.String (IsString)
 import Data.Text (Text)
@@ -152,7 +153,7 @@
 import GHCJS.DOM.KeyboardEvent as KeyboardEvent
 import GHCJS.DOM.MouseEvent
 import GHCJS.DOM.Node (appendChild_, getOwnerDocumentUnchecked, getParentNodeUnchecked, setNodeValue, toNode)
-import GHCJS.DOM.Types (liftJSM, askJSM, runJSM, JSM, MonadJSM, FocusEvent, IsElement, IsEvent, IsNode, KeyboardEvent, Node, TouchEvent, WheelEvent, uncheckedCastTo, ClipboardEvent)
+import GHCJS.DOM.Types (liftJSM, askJSM, runJSM, JSM, MonadJSM, FocusEvent, IsElement, IsEvent, IsNode, Node, TouchEvent, WheelEvent, uncheckedCastTo)
 import GHCJS.DOM.UIEvent
 #ifndef ghcjs_HOST_OS
 import Language.Javascript.JSaddle (call, eval) -- Avoid using eval in ghcjs. Use ffi instead
@@ -162,7 +163,6 @@
 import Reflex.Dom.Builder.Class
 import Reflex.Dynamic
 import Reflex.Host.Class
-import Reflex.Patch.DMapWithMove (PatchDMapWithMove(..))
 import Reflex.Patch.MapWithMove (PatchMapWithMove(..))
 import Reflex.PerformEvent.Base (PerformEventT)
 import Reflex.PerformEvent.Class
@@ -464,7 +464,11 @@
 #ifdef ghcjs_HOST_OS
 --NOTE: Although wrapping this javascript in a function seems unnecessary, GHCJS's optimizer will break it if it is entered without that wrapping (as of 2021-11-06)
 foreign import javascript unsafe
+#if __GLASGOW_HASKELL__ < 900
   "(function() { var n = $1; while (n['nextSibling']) { n['parentNode']['removeChild'](n['nextSibling']); }; })()"
+#else
+  "(function(n) { while (n['nextSibling']) { n['parentNode']['removeChild'](n['nextSibling']); }; })"
+#endif
   removeSubsequentNodes_ :: DOM.Node -> IO ()
 removeSubsequentNodes n = liftJSM $ removeSubsequentNodes_ (toNode n)
 #else
@@ -487,7 +491,11 @@
 #ifdef ghcjs_HOST_OS
 --NOTE: Although wrapping this javascript in a function seems unnecessary, GHCJS's optimizer will break it if it is entered without that wrapping (as of 2021-11-06)
 foreign import javascript unsafe
+#if __GLASGOW_HASKELL__ < 900
   "(function() { var df = $1; var s = $2; var e = $3; var x; for(;;) { x = s['nextSibling']; if(e===x) { break; }; df['appendChild'](x); } })()"
+#else
+  "(function(df, s, e) { var x; for(;;) { x = s['nextSibling']; if(e===x) { break; }; df['appendChild'](x); } })"
+#endif
   extractBetweenExclusive_ :: DOM.DocumentFragment -> DOM.Node -> DOM.Node -> IO ()
 extractBetweenExclusive df s e = liftJSM $ extractBetweenExclusive_ df (toNode s) (toNode e)
 #else
@@ -508,7 +516,11 @@
 #ifdef ghcjs_HOST_OS
 --NOTE: Although wrapping this javascript in a function seems unnecessary, GHCJS's optimizer will break it if it is entered without that wrapping (as of 2017-09-04)
 foreign import javascript unsafe
+#if __GLASGOW_HASKELL__ < 900
   "(function() { var x = $2; while(x !== $3) { var y = x['nextSibling']; $1['appendChild'](x); x = y; } })()"
+#else
+  "(function(_, x, $3) { while(x !== $3) { var y = x['nextSibling']; $1['appendChild'](x); x = y; } })"
+#endif
   extractUpTo_ :: DOM.DocumentFragment -> DOM.Node -> DOM.Node -> IO ()
 extractUpTo df s e = liftJSM $ extractUpTo_ df (toNode s) (toNode e)
 #else
@@ -662,7 +674,7 @@
 
 newtype GhcjsEventFilter er en = GhcjsEventFilter (GhcjsDomEvent en -> JSM (EventFlags, JSM (Maybe (er en))))
 
-data Pair1 (f :: k -> *) (g :: k -> *) (a :: k) = Pair1 (f a) (g a)
+data Pair1 (f :: k -> Type) (g :: k -> Type) (a :: k) = Pair1 (f a) (g a)
 
 data Maybe1 f a = Nothing1 | Just1 (f a)
 
@@ -1689,7 +1701,7 @@
 
 {-# INLINABLE traverseDMapWithKeyWithAdjust' #-}
 traverseDMapWithKeyWithAdjust'
-  :: forall s t m (k :: * -> *) v v'. (Adjustable t m, MonadHold t m, MonadFix m, MonadJSM m, PrimMonad m, GCompare k, RawDocument (DomBuilderSpace (HydrationDomBuilderT s t m)) ~ Document)
+  :: forall s t m (k :: Type -> Type) v v'. (Adjustable t m, MonadHold t m, MonadFix m, MonadJSM m, PrimMonad m, GCompare k, RawDocument (DomBuilderSpace (HydrationDomBuilderT s t m)) ~ Document)
   => (forall a. k a -> v a -> HydrationDomBuilderT s t m (v' a))
   -> DMap k v
   -> Event t (PatchDMap k v)
diff --git a/src/Reflex/Dom/Builder/InputDisabled.hs b/src/Reflex/Dom/Builder/InputDisabled.hs
--- a/src/Reflex/Dom/Builder/InputDisabled.hs
+++ b/src/Reflex/Dom/Builder/InputDisabled.hs
@@ -20,7 +20,6 @@
 #endif
 import Reflex
 import Reflex.Dom.Builder.Class
-import Reflex.Dom.Builder.Immediate (HasDocument (..))
 import Reflex.Host.Class
 
 -- | A DomBuilder transformer that disables all 'inputElement's,
diff --git a/src/Reflex/Dom/Builder/Static.hs b/src/Reflex/Dom/Builder/Static.hs
--- a/src/Reflex/Dom/Builder/Static.hs
+++ b/src/Reflex/Dom/Builder/Static.hs
@@ -18,8 +18,9 @@
 import Data.IORef (IORef)
 import Blaze.ByteString.Builder.Html.Utf8
 import Control.Lens hiding (element)
+import Control.Monad
 import Control.Monad.Exception
-import Control.Monad.Identity
+import Control.Monad.Fix
 import Control.Monad.Primitive
 import Control.Monad.Ref
 import Control.Monad.State.Strict
@@ -38,7 +39,7 @@
 import qualified Data.Map as Map
 import Data.Map.Misc (applyMap)
 import Data.Maybe (fromMaybe)
-import Data.Monoid ((<>))
+import Data.Kind (Type)
 import qualified Data.Set as Set
 import Data.Text (Text)
 import qualified Data.Text as T
@@ -144,7 +145,7 @@
 -- | Static documents don't process events, so all handlers are equivalent
 data StaticDomHandler (a :: k) (b :: k) = StaticDomHandler
 
-data StaticEventSpec (er :: EventTag -> *) = StaticEventSpec deriving (Generic)
+data StaticEventSpec (er :: EventTag -> Type) = StaticEventSpec deriving (Generic)
 
 instance Default (StaticEventSpec er)
 
@@ -219,7 +220,7 @@
       sample o
   return (result0, result')
 
-hoistDMapWithKeyWithAdjust :: forall (k :: * -> *) v v' t m p.
+hoistDMapWithKeyWithAdjust :: forall (k :: Type -> Type) v v' t m p.
   ( Adjustable t m
   , MonadHold t m
   , PatchTarget (p k (Constant (Behavior t Builder))) ~ DMap k (Constant (Behavior t Builder))
diff --git a/src/Reflex/Dom/Location.hs b/src/Reflex/Dom/Location.hs
--- a/src/Reflex/Dom/Location.hs
+++ b/src/Reflex/Dom/Location.hs
@@ -28,7 +28,6 @@
 import Control.Monad ((>=>))
 import Control.Monad.Fix (MonadFix)
 import Data.Align (align)
-import Data.Monoid
 import Data.Text (Text)
 import Data.These (These(..))
 import qualified GHCJS.DOM as DOM
diff --git a/src/Reflex/Dom/Main.hs b/src/Reflex/Dom/Main.hs
--- a/src/Reflex/Dom/Main.hs
+++ b/src/Reflex/Dom/Main.hs
@@ -33,14 +33,13 @@
 import Control.Concurrent
 import Control.Lens
 import Control.Monad
-import Control.Monad.Reader hiding (forM, forM_, mapM, mapM_, sequence, sequence_)
+import Control.Monad.Reader
 import Control.Monad.Ref
 import Data.ByteString (ByteString)
 import Data.Dependent.Sum (DSum (..))
 import Data.Foldable (for_)
 import Data.IORef
 import Data.Maybe
-import Data.Monoid ((<>))
 import Data.Text (Text)
 import qualified Data.Text as T
 import Data.Text.Encoding
@@ -58,7 +57,7 @@
 
 {-# INLINE mainHydrationWidgetWithHead #-}
 mainHydrationWidgetWithHead :: (forall x. HydrationWidget x ()) -> (forall x. HydrationWidget x ()) -> JSM ()
-mainHydrationWidgetWithHead = mainHydrationWidgetWithHead'
+mainHydrationWidgetWithHead head' body = mainHydrationWidgetWithHead' head' body
 
 {-# INLINABLE mainHydrationWidgetWithHead' #-}
 -- | Warning: `mainHydrationWidgetWithHead'` is provided only as performance tweak. It is expected to disappear in future releases.
@@ -67,7 +66,7 @@
 
 {-# INLINE mainHydrationWidgetWithSwitchoverAction #-}
 mainHydrationWidgetWithSwitchoverAction :: JSM () -> (forall x. HydrationWidget x ()) -> (forall x. HydrationWidget x ()) -> JSM ()
-mainHydrationWidgetWithSwitchoverAction = mainHydrationWidgetWithSwitchoverAction'
+mainHydrationWidgetWithSwitchoverAction switchoverAction head' body = mainHydrationWidgetWithSwitchoverAction' switchoverAction head' body
 
 {-# INLINABLE mainHydrationWidgetWithSwitchoverAction' #-}
 -- | Warning: `mainHydrationWidgetWithSwitchoverAction'` is provided only as performance tweak. It is expected to disappear in future releases.
@@ -187,7 +186,7 @@
 
 {-# INLINE mainWidget #-}
 mainWidget :: (forall x. Widget x ()) -> JSM ()
-mainWidget = mainWidget'
+mainWidget w = mainWidget' w
 
 {-# INLINABLE mainWidget' #-}
 -- | Warning: `mainWidget'` is provided only as performance tweak. It is expected to disappear in future releases.
diff --git a/src/Reflex/Dom/Old.hs b/src/Reflex/Dom/Old.hs
--- a/src/Reflex/Dom/Old.hs
+++ b/src/Reflex/Dom/Old.hs
@@ -11,6 +11,7 @@
 #ifdef USE_TEMPLATE_HASKELL
 {-# LANGUAGE TemplateHaskell #-}
 #endif
+{-# LANGUAGE TypeOperators #-}
 module Reflex.Dom.Old
        ( MonadWidget
        , El
diff --git a/src/Reflex/Dom/Prerender.hs b/src/Reflex/Dom/Prerender.hs
--- a/src/Reflex/Dom/Prerender.hs
+++ b/src/Reflex/Dom/Prerender.hs
@@ -11,6 +11,7 @@
 {-# LANGUAGE RecursiveDo #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE UndecidableInstances #-}
 {-# LANGUAGE UndecidableSuperClasses #-}
 
@@ -22,15 +23,16 @@
        , PrerenderBaseConstraints
        ) where
 
+import Control.Monad
+import Control.Monad.Fix
 import Control.Monad.Primitive (PrimMonad(..))
 import Control.Monad.Reader
 import Control.Monad.Ref (MonadRef(..), MonadAtomicRef(..))
 import Data.IORef (IORef, newIORef)
-import Data.Semigroup (Semigroup)
+import Data.Kind (Type)
 import Data.Semigroup.Commutative
 import Data.Text (Text)
 import Data.Void
-import Foreign.JavaScript.TH
 import GHCJS.DOM.Types (MonadJSM)
 import Reflex hiding (askEvents)
 import Reflex.Dom.Builder.Class
@@ -80,7 +82,7 @@
 
 class (PrerenderClientConstraint t (Client m), Client (Client m) ~ Client m, Prerender t (Client m)) => Prerender t m | m -> t where
   -- | Monad in which the client widget is built
-  type Client m :: * -> *
+  type Client m :: Type -> Type
   -- | Render the first widget on the server, and the second on the client. The
   -- hydration builder will run *both* widgets, updating the result dynamic at
   -- switchover time.
diff --git a/src/Reflex/Dom/WebSocket.hs b/src/Reflex/Dom/WebSocket.hs
--- a/src/Reflex/Dom/WebSocket.hs
+++ b/src/Reflex/Dom/WebSocket.hs
@@ -8,7 +8,6 @@
 {-# LANGUAGE ForeignFunctionInterface #-}
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
-{-# LANGUAGE JavaScriptFFI #-}
 {-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE NoMonomorphismRestriction #-}
@@ -40,9 +39,8 @@
 import Control.Concurrent.STM
 import Control.Exception
 import Control.Lens
-import Control.Monad hiding (forM, forM_, mapM, mapM_, sequence)
+import Control.Monad hiding (forM, mapM, mapM_, sequence)
 import Control.Monad.IO.Class
-import Control.Monad.State
 import Data.Aeson
 import Data.ByteString (ByteString)
 import Data.ByteString.Lazy (toStrict)
diff --git a/src/Reflex/Dom/Widget/Basic.hs b/src/Reflex/Dom/Widget/Basic.hs
--- a/src/Reflex/Dom/Widget/Basic.hs
+++ b/src/Reflex/Dom/Widget/Basic.hs
@@ -70,14 +70,12 @@
 import Reflex.PostBuild.Class
 import Reflex.Workflow
 
-import Control.Arrow
 import Control.Lens hiding (children, element)
-import Control.Monad.Reader hiding (forM, forM_, mapM, mapM_, sequence, sequence_)
+import Control.Monad.Fix
 import Data.Align
 import Data.Default
-import Data.Either
-import Data.Foldable
 import Data.Functor (void)
+import Data.Kind (Type)
 import Data.Map (Map)
 import qualified Data.Map as Map
 import Data.Map.Misc
@@ -87,8 +85,6 @@
 import Data.Text (Text)
 import qualified Data.Text as T
 import Data.These
-import Data.Traversable
-import Prelude hiding (mapM, mapM_, sequence, sequence_)
 
 -- | Breaks the given Map into pieces based on the given Set.  Each piece will contain only keys that are less than the key of the piece, and greater than or equal to the key of the piece with the next-smaller key.  There will be one additional piece containing all keys from the original Map that are larger or equal to the largest key in the Set.
 -- Either k () is used instead of Maybe k so that the resulting map of pieces is sorted so that the additional piece has the largest key.
@@ -341,5 +337,5 @@
         return $ fmap (const k) (_link_clicked a)
 
 class HasAttributes a where
-  type Attrs a :: *
+  type Attrs a :: Type
   attributes :: Lens' a (Attrs a)
diff --git a/src/Reflex/Dom/Widget/Input.hs b/src/Reflex/Dom/Widget/Input.hs
--- a/src/Reflex/Dom/Widget/Input.hs
+++ b/src/Reflex/Dom/Widget/Input.hs
@@ -13,12 +13,14 @@
 {-# LANGUAGE TemplateHaskell #-}
 #endif
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE UndecidableInstances #-}
 module Reflex.Dom.Widget.Input (module Reflex.Dom.Widget.Input, def, (&), (.~)) where
 
 import Prelude
 
 import Control.Lens hiding (element, ix)
+import Control.Monad
 import Control.Monad.Fix
 import Control.Monad.IO.Class
 import Control.Monad.Reader
@@ -27,10 +29,10 @@
 import Data.Dependent.Map (DMap)
 import qualified Data.Dependent.Map as DMap
 import Data.Functor.Misc
+import Data.Kind (Type)
 import Data.Map (Map)
 import qualified Data.Map as Map
 import Data.Maybe
-import Data.Semigroup
 import Data.Text (Text)
 import qualified Data.Text as T
 import GHCJS.DOM.HTMLInputElement (HTMLInputElement)
@@ -232,7 +234,7 @@
     , _checkbox_change = _inputElement_checkedChange i
     }
 
-type family CheckboxViewEventResultType (en :: EventTag) :: * where
+type family CheckboxViewEventResultType (en :: EventTag) :: Type where
   CheckboxViewEventResultType 'ClickTag = Bool
   CheckboxViewEventResultType t = EventResultType t
 
@@ -368,7 +370,7 @@
                        , _dropdownConfig_attributes = constDyn mempty
                        }
 
-type family DropdownViewEventResultType (en :: EventTag) :: * where
+type family DropdownViewEventResultType (en :: EventTag) :: Type where
   DropdownViewEventResultType 'ChangeTag = Text
   DropdownViewEventResultType t = EventResultType t
 
@@ -648,7 +650,7 @@
   setValue = checkboxConfig_setValue
 
 class HasValue a where
-  type Value a :: *
+  type Value a :: Type
   value :: a -> Value a
 
 instance HasValue (InputElement er d t) where
diff --git a/src/Reflex/Dom/Widget/Lazy.hs b/src/Reflex/Dom/Widget/Lazy.hs
--- a/src/Reflex/Dom/Widget/Lazy.hs
+++ b/src/Reflex/Dom/Widget/Lazy.hs
@@ -4,6 +4,7 @@
 {-# LANGUAGE RecursiveDo #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
 module Reflex.Dom.Widget.Lazy where
 
 import Reflex.Class
@@ -20,7 +21,6 @@
 import Data.Fixed
 import Data.Map (Map)
 import qualified Data.Map as Map
-import Data.Monoid
 import Data.Text (Text)
 import qualified Data.Text as T
 import GHCJS.DOM.Element
diff --git a/src/Reflex/Dom/Widget/Resize.hs b/src/Reflex/Dom/Widget/Resize.hs
--- a/src/Reflex/Dom/Widget/Resize.hs
+++ b/src/Reflex/Dom/Widget/Resize.hs
@@ -4,6 +4,7 @@
 {-# LANGUAGE RecursiveDo #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
 module Reflex.Dom.Widget.Resize where
 
 import Reflex.Class
@@ -16,12 +17,10 @@
 import Reflex.PostBuild.Class
 import Reflex.TriggerEvent.Class
 
-import Control.Monad
 import Control.Monad.Fix
 import Control.Monad.IO.Class
 import Data.Map (Map)
 import qualified Data.Map as Map
-import Data.Monoid
 import Data.Text (Text)
 import qualified Data.Text as T
 import GHCJS.DOM.Element
diff --git a/src/Reflex/Dom/Xhr.hs b/src/Reflex/Dom/Xhr.hs
--- a/src/Reflex/Dom/Xhr.hs
+++ b/src/Reflex/Dom/Xhr.hs
@@ -8,6 +8,7 @@
 #ifdef USE_TEMPLATE_HASKELL
 {-# LANGUAGE TemplateHaskell #-}
 #endif
+{-# LANGUAGE TypeOperators #-}
 
 -- | A module for performing asynchronous HTTP calls from JavaScript
 -- using the
diff --git a/src/Reflex/Dom/Xhr/Foreign.hs b/src/Reflex/Dom/Xhr/Foreign.hs
--- a/src/Reflex/Dom/Xhr/Foreign.hs
+++ b/src/Reflex/Dom/Xhr/Foreign.hs
@@ -1,5 +1,4 @@
 {-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE JavaScriptFFI #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 module Reflex.Dom.Xhr.Foreign (
diff --git a/src/Reflex/Dom/Xhr/FormData.hs b/src/Reflex/Dom/Xhr/FormData.hs
--- a/src/Reflex/Dom/Xhr/FormData.hs
+++ b/src/Reflex/Dom/Xhr/FormData.hs
@@ -14,7 +14,6 @@
 import Data.Text (Text)
 import Data.Traversable
 import qualified GHCJS.DOM.FormData as FD
-import Foreign.JavaScript.TH
 import GHCJS.DOM.File (getName)
 import GHCJS.DOM.Types (File, IsBlob)
 import Language.Javascript.JSaddle.Monad (MonadJSM, liftJSM)
diff --git a/test/gc.hs b/test/gc.hs
--- a/test/gc.hs
+++ b/test/gc.hs
@@ -11,7 +11,6 @@
 import Data.Text as T
 import Language.Javascript.JSaddle.Warp
 import Reflex.Dom.Core
-import Reflex.Time
 import System.Exit
 import System.Mem
 import System.Process
@@ -20,7 +19,7 @@
 import Test.Util.UnshareNetwork
 
 #if MIN_VERSION_base(4,11,0)
-import GHC.Stats (getRTSStatsEnabled, getRTSStats, RTSStats(..), gcdetails_live_bytes, gc)
+import GHC.Stats (getRTSStats, RTSStats(..), gcdetails_live_bytes, gc)
 currentBytesUsed :: RTSStats -> Int64
 currentBytesUsed = fromIntegral . gcdetails_live_bytes . gc
 #else
diff --git a/test/hlint.hs b/test/hlint.hs
--- a/test/hlint.hs
+++ b/test/hlint.hs
@@ -5,6 +5,7 @@
 main = do
   ideas <- hlint
     [ "."
+    , "--ignore=Functor law"
     , "--ignore=Redundant do"
     , "--ignore=Use camelCase"
     , "--ignore=Redundant $"
@@ -20,6 +21,7 @@
     , "--ignore=Unnecessary hiding" -- Interferes with cross-version compatibility
     , "--ignore=Use <$>"
     , "--ignore=Reduce duplication" --TODO: Re-enable this test
+    , "--ignore=Eta reduce" -- simplified subsumption
     , "--ignore=Use list comprehension"
     , "--ignore=Evaluate"
     , "--cpp-define=USE_TEMPLATE_HASKELL"
diff --git a/test/hydration.hs b/test/hydration.hs
--- a/test/hydration.hs
+++ b/test/hydration.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE ConstraintKinds #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE FlexibleInstances #-}
@@ -58,7 +59,6 @@
 import Network.Wai
 import Network.WebSockets
 import Reflex.Dom.Core
-import Reflex.Dom.Widget.Input (dropdown)
 import Reflex.Patch.DMapWithMove
 import System.Directory
 import System.Environment
@@ -89,8 +89,10 @@
 import Test.Util.ChromeFlags
 import Test.Util.UnshareNetwork
 
--- ORPHAN: https://github.com/kallisti-dev/hs-webdriver/pull/167
+
+#if !MIN_VERSION_webdriver(0,10,0)
 deriving instance MonadMask WD
+#endif
 
 chromium :: FilePath
 chromium = $(staticWhich "chromium")
@@ -118,18 +120,11 @@
 chromeConfig :: Text -> [Text] -> WD.WDConfig
 chromeConfig fp flags = WD.useBrowser (WD.chrome { WD.chromeBinary = Just $ T.unpack fp, WD.chromeOptions = T.unpack <$> flags }) WD.defaultConfig
 
-keyMap :: DMap DKey Identity
-keyMap = DMap.fromList
-  [ Key_Int ==> 0
-  , Key_Char ==> 'A'
-  ]
-
 data DKey a where
   Key_Int :: DKey Int
   Key_Char :: DKey Char
   Key_Bool :: DKey Bool
 
-
 textKey :: DKey a -> Text
 textKey = \case
   Key_Int -> "Key_Int"
@@ -141,6 +136,21 @@
 deriveGCompare ''DKey
 deriveGShow ''DKey
 
+keyMap :: DMap DKey Identity
+keyMap = DMap.fromList
+  [ Key_Int ==> 0
+  , Key_Char ==> 'A'
+  ]
+
+data Key2 a where
+  Key2_Int :: Int -> Key2 Int
+  Key2_Char :: Char -> Key2 Char
+
+deriveGEq ''Key2
+deriveGCompare ''Key2
+deriveGShow ''Key2
+deriveArgDict ''Key2
+
 deriving instance MonadFail WD
 
 main :: IO ()
@@ -166,11 +176,11 @@
         r <- m
         putStrLnDebug "after"
         return r
-      testWidgetStatic :: WD b -> (forall m js. TestWidget (SpiderTimeline Global) m => m ()) -> WD b
+      testWidgetStatic :: WD b -> (forall m. TestWidget (SpiderTimeline Global) m => m ()) -> WD b
       testWidgetStatic = testWidgetStaticDebug withDebugging
-      testWidget :: WD () -> WD b -> (forall m js. TestWidget (SpiderTimeline Global) m => m ()) -> WD b
+      testWidget :: WD () -> WD b -> (forall m. TestWidget (SpiderTimeline Global) m => m ()) -> WD b
       testWidget = testWidgetDebug True withDebugging
-      testWidget' :: WD a -> (a -> WD b) -> (forall m js. TestWidget (SpiderTimeline Global) m => m ()) -> WD b
+      testWidget' :: WD a -> (a -> WD b) -> (forall m. TestWidget (SpiderTimeline Global) m => m ()) -> WD b
       testWidget' = testWidgetDebug' True withDebugging
   session' "text" $ do
     it "works" $ runWD $ do
@@ -1722,7 +1732,7 @@
   :: Bool
   -> WD b
   -- ^ Webdriver commands to run before JS runs and after hydration switchover
-  -> (forall m js. TestWidget (SpiderTimeline Global) m => m ())
+  -> (forall m. TestWidget (SpiderTimeline Global) m => m ())
   -- ^ Widget we are testing
   -> WD b
 testWidgetStaticDebug withDebugging w = testWidgetDebug True withDebugging (void w) w
@@ -1735,7 +1745,7 @@
   -- ^ Webdriver commands to run before the JS runs (i.e. on the statically rendered page)
   -> WD b
   -- ^ Webdriver commands to run after hydration switchover
-  -> (forall m js. TestWidget (SpiderTimeline Global) m => m ())
+  -> (forall m. TestWidget (SpiderTimeline Global) m => m ())
   -- ^ Widget we are testing
   -> WD b
 testWidgetDebug hardFailure withDebugging beforeJS afterSwitchover =
@@ -1752,7 +1762,7 @@
   -- ^ Webdriver commands to run before the JS runs (i.e. on the statically rendered page)
   -> (a -> WD b)
   -- ^ Webdriver commands to run after hydration switchover
-  -> (forall m js. TestWidget (SpiderTimeline Global) m => m ())
+  -> (forall m. TestWidget (SpiderTimeline Global) m => m ())
   -- ^ Widget we are testing (contents of body)
   -> WD b
 testWidgetDebug' hardFailure withDebugging beforeJS afterSwitchover bodyWidget = do
@@ -1817,12 +1827,3 @@
   (liftIO $ Async.async f)
   (liftIO . Async.uninterruptibleCancel)
   (const g)
-
-data Key2 a where
-  Key2_Int :: Int -> Key2 Int
-  Key2_Char :: Char -> Key2 Char
-
-deriveGEq ''Key2
-deriveGCompare ''Key2
-deriveGShow ''Key2
-deriveArgDict ''Key2
