diff --git a/Rattus.cabal b/Rattus.cabal
--- a/Rattus.cabal
+++ b/Rattus.cabal
@@ -1,6 +1,6 @@
 cabal-version:       1.18
 name:                Rattus
-version:             0.5.0.1
+version:             0.5.1
 category:            FRP
 synopsis:            A modal FRP language
 description:
@@ -131,7 +131,7 @@
 custom-setup
   setup-depends:
     base  >= 4.5 && < 5,
-    Cabal >= 1.18
+    Cabal >= 1.18  && < 4
 
 
 library
@@ -155,7 +155,7 @@
                        Rattus.Plugin.Utils
                        Rattus.Plugin.Dependency
                        Rattus.Plugin.StableSolver
-  build-depends:       base >=4.12 && <5, containers, ghc >= 8.6 && < 9.3, ghc-prim, simple-affine-space, transformers
+  build-depends:       base >=4.12 && <5, containers, ghc >= 8.6 && < 9.7, ghc-prim, simple-affine-space, transformers
   hs-source-dirs:      src
   default-language:    Haskell2010
   ghc-options:         -W
diff --git a/docs/paper.pdf b/docs/paper.pdf
Binary files a/docs/paper.pdf and b/docs/paper.pdf differ
diff --git a/src/Rattus/Event.hs b/src/Rattus/Event.hs
--- a/src/Rattus/Event.hs
+++ b/src/Rattus/Event.hs
@@ -9,6 +9,8 @@
   , never
   , switch
   , switchTrans
+  , dswitchTrans
+  , combine
   , Event
   , trigger
   , triggerMap
@@ -20,7 +22,7 @@
 import Rattus.Stream hiding (map)
 import qualified Rattus.Stream as Str
 
-import Prelude hiding (map)
+import Prelude hiding (map,zipWith)
 
 -- | Events are simply streams of 'Maybe''s.
 type Event a = Str (Maybe' a)
@@ -45,6 +47,16 @@
 switch  _xs       (Just' (a ::: as) ::: fas)   = a ::: (delay switch <#> as <#> fas)
 
 
+-- | @combine f s e@ is similar to @switch s e@, but instead of
+-- switching to new streams @s'@ every time the event 'e' occurs with
+-- some value @s'@, the new stream @s'@ is combined with the current
+-- stream @s@ using @zipWith f s' s@.
+combine :: Box (a -> a -> a) -> Str a -> Event (Str a) -> Str a
+combine f (x ::: xs) (Nothing' ::: fas) = x  ::: delay (combine f (adv xs) (adv fas))
+combine f xs         (Just' as ::: fas) = x' ::: delay (combine f (adv xs') (adv fas))
+  where (x' ::: xs') = zipWith f xs as
+
+
 -- | Like 'switch' but works on stream functions instead of
 -- streams. That is, @switchTrans s e@ will behave like @s@ but
 -- switches to @s'$ every time the event 'e' occurs with some value
@@ -57,6 +69,17 @@
 switchTrans' (b ::: bs) (Nothing' ::: fs) (_:::as) = b ::: (delay switchTrans' <#> bs <#> fs <#> as)
 switchTrans' _xs        (Just' f ::: fs)  as@(_:::as') = b' ::: (delay switchTrans' <#> bs' <#> fs <#> as')
   where (b' ::: bs') = f as
+
+
+
+-- | Like 'switchTrans' but takes a delayed event as input, which
+-- allows the switch to incorporate feedback from itself.
+dswitchTrans :: (Str a -> Str b) -> O (Event (Str a -> Str b)) -> (Str a -> Str b)
+dswitchTrans f es as = dswitchTrans' (f as) es as
+
+-- | Helper function for 'dswitchTrans'.
+dswitchTrans' :: Str b -> O (Event (Str a -> Str b)) -> Str a -> Str b
+dswitchTrans' (b ::: bs) de (_:::as) = b ::: (delay switchTrans' <#> bs <#> de <#> as)
 
 
 -- | Trigger an event as every time the given predicate turns true on
diff --git a/src/Rattus/Plugin.hs b/src/Rattus/Plugin.hs
--- a/src/Rattus/Plugin.hs
+++ b/src/Rattus/Plugin.hs
@@ -73,9 +73,11 @@
     es' <- mapM (\ (v,e) -> do
                     e' <- toSingleTick e
                     lazy <- allowLazyData guts v
+                    allowRec <- allowRecursion guts v
                     e'' <- strictifyExpr (SCxt (nameSrcSpan $ getName v) (not lazy))e'
                     checkExpr CheckExpr{ recursiveSet = Set.fromList vs, oldExpr = e,
-                                         fatalError = False, verbose = debugMode opts} e''
+                                         fatalError = False, verbose = debugMode opts,
+                                         allowRecExp = allowRec} e''
                     return e'') bs
     return (Rec (zip vs es'))
   else return b
@@ -88,9 +90,11 @@
       -- liftIO $ putStrLn "-------- new --------"
       -- liftIO $ putStrLn (showSDocUnsafe (ppr e'))
       lazy <- allowLazyData guts v
+      allowRec <- allowRecursion guts v
       e'' <- strictifyExpr (SCxt (nameSrcSpan $ getName v) (not lazy)) e'
       checkExpr CheckExpr{ recursiveSet = Set.empty, oldExpr = e,
-                           fatalError = False, verbose = debugMode opts} e''
+                           fatalError = False, verbose = debugMode opts,
+                           allowRecExp = allowRec } e''
       return (NonRec v e'')
     else return b
 
@@ -108,6 +112,11 @@
 allowLazyData guts bndr = do
   l <- annotationsOn guts bndr :: CoreM [Rattus]
   return (AllowLazyData `elem` l)
+
+allowRecursion :: ModGuts -> CoreBndr -> CoreM Bool
+allowRecursion guts bndr = do
+  l <- annotationsOn guts bndr :: CoreM [Rattus]
+  return (AllowRecursion `elem` l)
 
 
 shouldTransform :: ModGuts -> CoreBndr -> CoreM Bool
diff --git a/src/Rattus/Plugin/Annotation.hs b/src/Rattus/Plugin/Annotation.hs
--- a/src/Rattus/Plugin/Annotation.hs
+++ b/src/Rattus/Plugin/Annotation.hs
@@ -26,8 +26,14 @@
 -- > {-# ANN myFunction AllowLazyData #-}
 -- >
 -- > {-# ANN module AllowLazyData #-}
+--
+-- Rattus only allows guarded recursion, i.e. recursive calls must
+-- occur in the scope of a tick. Structural recursion over strict data
+-- types is safe as well, but is currently not checked. To disable the
+-- guarded recursion check, annotate the module or function with
+-- 'AllowRecursion'.
 
-data Rattus = Rattus | NotRattus | AllowLazyData deriving (Typeable, Data, Show, Eq)
+data Rattus = Rattus | NotRattus | AllowLazyData | AllowRecursion deriving (Typeable, Data, Show, Ord, Eq)
 
 
 -- | This annotation type is for internal use only.
diff --git a/src/Rattus/Plugin/CheckSingleTick.hs b/src/Rattus/Plugin/CheckSingleTick.hs
--- a/src/Rattus/Plugin/CheckSingleTick.hs
+++ b/src/Rattus/Plugin/CheckSingleTick.hs
@@ -54,7 +54,8 @@
     primAlias :: Map Var Prim,
     -- number of ticks (for recursive calls). This is to allow
     -- recursive definitions of the form @f = delay (delay (adv f))@.
-    ticks :: Int} 
+    ticks :: Int,
+    allowRecursion :: Bool} 
 
 primMap :: Map FastString Prim
 primMap = Map.fromList
@@ -89,14 +90,17 @@
 getScope  :: Ctx -> Var -> Scope
 getScope c v =
     if v `Set.member` recDef c then
-      if ticks c > 0 then Visible
+      if ticks c > 0 || allowRecursion c then Visible
       else Hidden ("(Mutually) recursive call to " <> ppr v <> " must occur under delay")
     else case Map.lookup v (hidden c) of
       Just reason ->
         if (isStable (stableTypes c) (varType v)) then Visible
         else case reason of
-          NestedRec rv -> Hidden ("Variable " <> ppr v <> " is no longer in scope:" $$ "It appears in a local recursive definition (namely of " <> ppr rv <> ")"
-                       $$ "and is of type " <> ppr (varType v) <> ", which is not stable.")
+          NestedRec rv ->
+            if allowRecursion c then Visible
+            else Hidden ("Variable " <> ppr v <> " is no longer in scope:"
+                         $$ "It appears in a local recursive definition (namely of " <> ppr rv <> ")"
+                         $$ "and is of type " <> ppr (varType v) <> ", which is not stable.")
           BoxApp -> Hidden ("Variable " <> ppr v <> " is no longer in scope:" $$
                        "It occurs under " <> keyword "box" $$ "and is of type " <> ppr (varType v) <> ", which is not stable.")
           AdvApp -> Hidden ("Variable " <> ppr v <> " is no longer in scope: It occurs under adv.")
@@ -123,16 +127,17 @@
   return (Just (TypeError (pickFirst (srcLoc cxt) (nameSrcSpan (varName var))) doc))
 
 
-emptyCtx :: Set Var -> Ctx
-emptyCtx vars =
+emptyCtx :: CheckExpr -> Ctx
+emptyCtx c =
   Ctx { current =  Set.empty,
         earlier = Nothing,
         hidden = Map.empty,
         srcLoc = noLocationInfo,
-        recDef = vars,
+        recDef = recursiveSet c,
         primAlias = Map.empty,
         stableTypes = Set.empty,
-        ticks = 0}
+        ticks = 0,
+        allowRecursion = allowRecExp c}
 
 
 isPrimExpr :: Ctx -> Expr Var -> Maybe (Prim,Var)
@@ -169,12 +174,13 @@
   recursiveSet :: Set Var,
   oldExpr :: Expr Var,
   fatalError :: Bool,
-  verbose :: Bool
+  verbose :: Bool,
+  allowRecExp :: Bool
   }
 
 checkExpr :: CheckExpr -> Expr Var -> CoreM ()
 checkExpr c e = do
-  res <- checkExpr' (emptyCtx (recursiveSet c)) e
+  res <- checkExpr' (emptyCtx c) e
   case res of
     Nothing -> return ()
     Just (TypeError src doc) ->
diff --git a/src/Rattus/Plugin/Dependency.hs b/src/Rattus/Plugin/Dependency.hs
--- a/src/Rattus/Plugin/Dependency.hs
+++ b/src/Rattus/Plugin/Dependency.hs
@@ -6,7 +6,7 @@
 
 -- | This module is used to perform a dependency analysis of top-level
 -- function definitions, i.e. to find out which defintions are
--- (mutual) recursive. To this end, this module also provides a
+-- (mutual) recursive. To this end, this module also provides
 -- functions to compute, bound variables and variable occurrences.
 
 module Rattus.Plugin.Dependency (dependency, HasBV (..),printBinds) where
@@ -37,7 +37,9 @@
 import HsBinds
 #endif
 
-#if __GLASGOW_HASKELL__ >= 902
+#if __GLASGOW_HASKELL__ >= 904
+import GHC.Parser.Annotation
+#elif __GLASGOW_HASKELL__ >= 902
 import Language.Haskell.Syntax.Extension
 import GHC.Parser.Annotation
 #endif
@@ -77,11 +79,16 @@
 
 printBind (L _ FunBind{fun_id = L _ name}) = 
   liftIO $ putStr $ (getOccString name ++ " ")
+printBind (L _ (VarBind {var_id = name})) =   liftIO $ putStr $ (getOccString name ++ " ")
+#if __GLASGOW_HASKELL__ < 904
 printBind (L _ (AbsBinds {abs_exports = exp})) = 
+#else
+printBind (L _ (XHsBindsLR (AbsBinds {abs_exports = exp}))) = 
+#endif
   mapM_ (\ e -> liftIO $ putStr $ ((getOccString $ abe_poly e)  ++ " ")) exp
-printBind (L _ (VarBind {var_id = name})) =   liftIO $ putStr $ (getOccString name ++ " ")
 printBind _ = return ()
 
+
 -- | Computes the variables that are bound by a given piece of syntax.
 
 class HasBV a where
@@ -89,12 +96,16 @@
 
 instance HasBV (HsBindLR GhcTc GhcTc) where
   getBV (FunBind{fun_id = L _ v}) = Set.singleton v
-  getBV (AbsBinds {abs_exports = es}) = Set.fromList (map abe_poly es)
   getBV (PatBind {pat_lhs = pat}) = getBV pat
   getBV (VarBind {var_id = v}) = Set.singleton v
   getBV PatSynBind{} = Set.empty
 #if __GLASGOW_HASKELL__ < 900
   getBV (XHsBindsLR e) = getBV e
+  getBV (AbsBinds {abs_exports = es}) = Set.fromList (map abe_poly es)
+#elif __GLASGOW_HASKELL__ < 904
+  getBV (AbsBinds {abs_exports = es}) = Set.fromList (map abe_poly es)
+#else
+  getBV (XHsBindsLR (AbsBinds {abs_exports = es})) = Set.fromList (map abe_poly es)
 #endif
   
 instance HasBV a => HasBV (GenLocated b a) where
@@ -103,7 +114,11 @@
 instance HasBV a => HasBV [a] where
   getBV ps = foldl (\s p -> getBV p `Set.union` s) Set.empty ps
 
-
+#if __GLASGOW_HASKELL__ >= 904
+getRecFieldRhs = hfbRHS
+#else
+getRecFieldRhs = hsRecFieldArg
+#endif
 
 #if __GLASGOW_HASKELL__ >= 902
 getConBV (PrefixCon _ ps) = getBV ps
@@ -112,35 +127,54 @@
 #endif
 getConBV (InfixCon p p') = getBV p `Set.union` getBV p'
 getConBV (RecCon (HsRecFields {rec_flds = fs})) = foldl run Set.empty fs
-      where run s (L _ f) = getBV (hsRecFieldArg f) `Set.union` s
+      where run s (L _ f) = getBV (getRecFieldRhs f) `Set.union` s
 
-#if __GLASGOW_HASKELL__ >= 900
+#if __GLASGOW_HASKELL__ >= 900 && __GLASGOW_HASKELL__ < 904
 instance HasBV CoPat where
   getBV CoPat {co_pat_inner = p} = getBV p
+#elif __GLASGOW_HASKELL__ >= 904
+instance HasBV XXPatGhcTc where
+  getBV CoPat {co_pat_inner = p} = getBV p
+  getBV (ExpansionPat _ p) = getBV p
 #endif
 
 instance HasBV (Pat GhcTc) where
   getBV (VarPat _ (L _ v)) = Set.singleton v
   getBV (LazyPat _ p) = getBV p
+#if __GLASGOW_HASKELL__ >= 906
+  getBV (AsPat _ (L _ v) _ p) = Set.insert v (getBV p)
+#else
   getBV (AsPat _ (L _ v) p) = Set.insert v (getBV p)
-  getBV (ParPat _ p) = getBV p
+#endif
   getBV (BangPat _ p) = getBV p
   getBV (ListPat _ ps) = getBV ps
   getBV (TuplePat _ ps _) = getBV ps
   getBV (SumPat _ p _ _) = getBV p
   getBV (ViewPat _ _ p) = getBV p
+
   getBV (SplicePat _ sp) =
     case sp of
+#if __GLASGOW_HASKELL__ < 906
       HsTypedSplice _ _ v _ -> Set.singleton v
+      HsSpliced _ _ (HsSplicedPat p) -> getBV p
       HsUntypedSplice _ _ v _ ->  Set.singleton v
       HsQuasiQuote _ p p' _ _ -> Set.fromList [p,p']
-      HsSpliced _ _ (HsSplicedPat p) -> getBV p
       _ -> Set.empty
+#else
+      HsUntypedSpliceExpr _ e -> getFV e
+      HsQuasiQuote _ v _  -> Set.singleton v
+#endif
+
   getBV (NPlusKPat _ (L _ v) _ _ _ _) = Set.singleton v
   getBV (NPat {}) = Set.empty
   getBV (XPat p) = getBV p
   getBV (WildPat {}) = Set.empty
   getBV (LitPat {}) = Set.empty
+#if __GLASGOW_HASKELL__ >= 904  
+  getBV (ParPat _ _ p _) = getBV p
+#else
+  getBV (ParPat _ p) = getBV p
+#endif
 #if __GLASGOW_HASKELL__ >= 900
   getBV (ConPat {pat_args = con}) = getConBV con
 #else
@@ -154,14 +188,16 @@
   getBV (SigPat _ p)   = getBV p
 #endif
 
+#if __GLASGOW_HASKELL__ >= 904
 
-#if __GLASGOW_HASKELL__ >= 810
+#elif __GLASGOW_HASKELL__ >= 810
 instance HasBV NoExtCon where
 #else
 instance HasBV NoExt where
 #endif
+#if __GLASGOW_HASKELL__ < 904
   getBV _ = Set.empty
-
+#endif
 
 -- | Syntax that may contain variables.
 class HasFV a where
@@ -235,8 +271,12 @@
   getFV FunBind {fun_matches = ms} = getFV ms
   getFV PatBind {pat_rhs = rhs} = getFV rhs
   getFV VarBind {var_rhs = rhs} = getFV rhs
-  getFV AbsBinds {abs_binds = bs} = getFV bs
   getFV PatSynBind {} = Set.empty
+#if __GLASGOW_HASKELL__ < 904
+  getFV AbsBinds {abs_binds = bs} = getFV bs
+#else
+  getFV (XHsBindsLR AbsBinds {abs_binds = bs}) = getFV bs
+#endif
 #if __GLASGOW_HASKELL__ < 900
   getFV (XHsBindsLR e) = getFV e
 #endif
@@ -295,21 +335,26 @@
 #endif
   getFV HsRecFields{rec_flds = fs} = getFV fs
 
-
-#if __GLASGOW_HASKELL__ >= 902
+#if __GLASGOW_HASKELL__ >= 904
+instance HasFV (HsFieldBind o (GenLocated SrcSpanAnnA (HsExpr GhcTc))) where
+#elif __GLASGOW_HASKELL__ >= 902
 instance HasFV (HsRecField' o (GenLocated SrcSpanAnnA (HsExpr GhcTc))) where
 #else
 instance HasFV (HsRecField' o (LHsExpr GhcTc)) where
 #endif
-  getFV HsRecField {hsRecFieldArg = arg}  = getFV arg
+  getFV rf  = getFV (getRecFieldRhs rf)
 
 instance HasFV (ArithSeqInfo GhcTc) where
   getFV (From e) = getFV e
   getFV (FromThen e1 e2) = getFV e1 `Set.union` getFV e2
   getFV (FromTo e1 e2) = getFV e1 `Set.union` getFV e2
   getFV (FromThenTo e1 e2 e3) = getFV e1 `Set.union` getFV e2 `Set.union` getFV e3
-
+  
+#if __GLASGOW_HASKELL__ >= 904
+instance HasFV (HsQuote GhcTc) where
+#else
 instance HasFV (HsBracket GhcTc) where
+#endif
   getFV (ExpBr _ e) = getFV e
   getFV (VarBr _ _ e) = getFV e
   getFV _ = Set.empty
@@ -319,12 +364,19 @@
   getFV (HsCmdArrForm _ e _ _ cmd) = getFV e `Set.union` getFV cmd
   getFV (HsCmdApp _ e1 e2) = getFV e1 `Set.union` getFV e2
   getFV (HsCmdLam _ l) = getFV l
-  getFV (HsCmdPar _ cmd) = getFV cmd
   getFV (HsCmdCase _ _ mg) = getFV mg
   getFV (HsCmdIf _ _ e1 e2 e3) = getFV e1 `Set.union` getFV e2 `Set.union` getFV e3
-  getFV (HsCmdLet _ bs _) = getFV bs
   getFV (HsCmdDo _ cmd) = getFV cmd
-#if __GLASGOW_HASKELL__ >= 900
+#if __GLASGOW_HASKELL__ >= 904
+  getFV (HsCmdPar _ _ cmd _) = getFV cmd
+  getFV (HsCmdLet _ _ bs _ _) = getFV bs
+#else
+  getFV (HsCmdPar _ cmd) = getFV cmd
+  getFV (HsCmdLet _ bs _) = getFV bs
+#endif
+#if __GLASGOW_HASKELL__ >= 904
+  getFV (HsCmdLamCase _ _ mg) = getFV mg
+#elif __GLASGOW_HASKELL__ >= 900
   getFV (HsCmdLamCase _ mg) = getFV mg
 #else
   getFV (HsCmdWrap _ _ cmd) = getFV cmd
@@ -341,25 +393,20 @@
 instance HasFV (HsExpr GhcTc) where
   getFV (HsVar _ v) = getFV v
   getFV HsUnboundVar {} = Set.empty
-  getFV HsConLikeOut {} = Set.empty
-  getFV HsRecFld {} = Set.empty
   getFV HsOverLabel {} = Set.empty
   getFV HsIPVar {} = Set.empty
   getFV HsOverLit {} = Set.empty
   getFV HsLit {} = Set.empty
   getFV (HsLam _ mg) = getFV mg
-  getFV (HsLamCase _ mg) = getFV mg
   getFV (HsApp _ e1 e2) = getFV e1 `Set.union` getFV e2      
   getFV (OpApp _ e1 e2 e3) = getFV e1 `Set.union` getFV e2 `Set.union` getFV e3
   getFV (NegApp _ e _) = getFV e
-  getFV (HsPar _ e) = getFV e
   getFV (SectionL _ e1 e2) = getFV e1 `Set.union` getFV e2
   getFV (SectionR _ e1 e2) = getFV e1 `Set.union` getFV e2
   getFV (ExplicitTuple _ es _) = getFV es
   getFV (ExplicitSum _ _ _ e) = getFV e
   getFV (HsCase _ e mg) = getFV e  `Set.union` getFV mg
   getFV (HsMultiIf _ es) = getFV es
-  getFV (HsLet _ bs e) = getFV bs `Set.union` getFV e
   getFV (HsDo _ _ e) = getFV e
 #if __GLASGOW_HASKELL__ >= 902
   getFV HsProjection {} = Set.empty
@@ -373,17 +420,39 @@
 #endif
   getFV (RecordCon {rcon_flds = fs}) = getFV fs
   getFV (ArithSeq _ _ e) = getFV e
-  getFV (HsBracket _ e) = getFV e
-  getFV HsRnBracketOut {} = Set.empty
-  getFV HsTcBracketOut {} = Set.empty
+#if __GLASGOW_HASKELL__ >= 906
+  getFV HsTypedSplice{} = Set.empty
+  getFV HsUntypedSplice{} = Set.empty
+#else
   getFV HsSpliceE{} = Set.empty
+#endif
   getFV (HsProc _ _ e) = getFV e
-  getFV (HsStatic _ e) = getFV e  
-  getFV (HsTick _ _ e) = getFV e
-  getFV (HsBinTick _ _ _ e) = getFV e
+  getFV (HsStatic _ e) = getFV e
   getFV (XExpr e) = getFV e
-  
-#if __GLASGOW_HASKELL__ >= 808
+#if __GLASGOW_HASKELL__ >= 904
+  getFV (HsPar _ _ e _) = getFV e  
+  getFV (HsLamCase _ _ mg) = getFV mg
+  getFV (HsLet _ _ bs _ e) = getFV bs `Set.union` getFV e
+  getFV HsRecSel {} = Set.empty
+  getFV (HsTypedBracket _ e) = getFV e
+  getFV (HsUntypedBracket _ e) = getFV e
+#else  
+  getFV (HsBinTick _ _ _ e) = getFV e
+  getFV (HsTick _ _ e) = getFV e
+  getFV (HsLet _ bs e) = getFV bs `Set.union` getFV e
+  getFV (HsPar _ e) = getFV e
+  getFV (HsLamCase _ mg) = getFV mg
+  getFV HsConLikeOut {} = Set.empty
+  getFV HsRecFld {} = Set.empty
+  getFV (HsBracket _ e) = getFV e
+  getFV HsRnBracketOut {} = Set.empty
+  getFV HsTcBracketOut {} = Set.empty
+#endif
+
+#if __GLASGOW_HASKELL__ >= 906
+  getFV (HsAppType _ e _ _) = getFV e
+  getFV (ExprWithTySig _ e _) = getFV e  
+#elif __GLASGOW_HASKELL__ >= 808
   getFV (HsAppType _ e _) = getFV e
   getFV (ExprWithTySig _ e _) = getFV e  
 #else
@@ -416,6 +485,12 @@
 instance HasFV XXExprGhcTc where
   getFV (WrapExpr e) = getFV e
   getFV (ExpansionExpr (HsExpanded _e1 e2)) = getFV e2
+#if __GLASGOW_HASKELL__ >= 904  
+  getFV (HsTick _ e) = getFV e
+  getFV (HsBinTick _ _ e) = getFV e
+  getFV ConLikeTc{} = Set.empty
+#endif
+
 
 instance HasFV (e GhcTc) => HasFV (HsWrap e) where
   getFV (HsWrap _ e) = getFV e
diff --git a/src/Rattus/Plugin/ScopeCheck.hs b/src/Rattus/Plugin/ScopeCheck.hs
--- a/src/Rattus/Plugin/ScopeCheck.hs
+++ b/src/Rattus/Plugin/ScopeCheck.hs
@@ -5,6 +5,7 @@
 {-# LANGUAGE TupleSections #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE ImplicitParams #-}
+{-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE CPP #-}
 
@@ -62,6 +63,8 @@
 import Data.Either
 import Data.Maybe
 
+import Data.Data hiding (tyConName)
+
 import Control.Monad
 
 type ErrorMsg = (Severity,SrcSpan,SDoc)
@@ -100,7 +103,9 @@
     -- | This flag indicates whether the context was 'stabilized'
     -- (stripped of all non-stable stuff). It is set when typechecking
     -- 'box', 'arr' and guarded recursion.
-    stabilized :: Maybe StableReason}
+    stabilized :: Maybe StableReason,
+    -- | Allow general recursion.
+    allowRecursion :: Bool}
 
 
 
@@ -108,8 +113,8 @@
 -- non-recursive definitions, the argument is @Nothing@. Otherwise, it
 -- contains the recursively defined variables along with the location
 -- of the recursive definition.
-emptyCtxt :: ErrorMsgsRef -> Maybe (Set Var,SrcSpan) -> Ctxt
-emptyCtxt em mvar =
+emptyCtxt :: ErrorMsgsRef -> Maybe (Set Var,SrcSpan) -> Bool -> Ctxt
+emptyCtxt em mvar allowRec =
   Ctxt { errorMsgs = em,
          current =  Set.empty,
          earlier = Left NoDelay,
@@ -120,7 +125,8 @@
          stableTypes = Set.empty,
          stabilized = case mvar of
            Just (_,loc) ->  Just (StableRec loc)
-           _  ->  Nothing}
+           _  ->  Nothing,
+         allowRecursion = allowRec}
 
 -- | A local context, consisting of a set of variables.
 type LCtxt = Set Var
@@ -336,8 +342,13 @@
 checkPatBind' PatBind{} = do
   printMessage' SevError ("(Mutual) recursive pattern binding definitions are not supported in Rattus")
   return False
-         
-checkPatBind' AbsBinds {abs_binds = binds} = liftM and (mapM checkPatBind (bagToList binds))
+#if __GLASGOW_HASKELL__ < 904
+checkPatBind' AbsBinds {abs_binds = binds} = 
+#else
+checkPatBind' (XHsBindsLR AbsBinds {abs_binds = binds}) = 
+#endif
+  liftM and (mapM checkPatBind (bagToList binds))
+
 checkPatBind' _ = return True
 
 
@@ -390,11 +401,15 @@
 getAllBV :: GenLocated l (HsBindLR GhcTc GhcTc) -> Set Var
 getAllBV (L _ b) = getAllBV' b where
   getAllBV' (FunBind{fun_id = L _ v}) = Set.singleton v
+#if __GLASGOW_HASKELL__ < 904
   getAllBV' (AbsBinds {abs_exports = es, abs_binds = bs}) = Set.fromList (map abe_poly es) `Set.union` foldMap getBV bs
+  getAllBV' XHsBindsLR{} = Set.empty
+#else
+  getAllBV' (XHsBindsLR (AbsBinds {abs_exports = es, abs_binds = bs})) = Set.fromList (map abe_poly es) `Set.union` foldMap getBV bs
+#endif
   getAllBV' (PatBind {pat_lhs = pat}) = getBV pat
   getAllBV' (VarBind {var_id = v}) = Set.singleton v
   getAllBV' PatSynBind{} = Set.empty
-  getAllBV' XHsBindsLR{} = Set.empty
 
 
 -- Check nested bindings
@@ -508,26 +523,42 @@
                             <> " There is a delay, but its scope is interrupted by " <> tickHidden hr <> ".")
     _ -> liftM2 (&&) (check e1)  (check e2)
   check HsUnboundVar{}  = return True
+#if __GLASGOW_HASKELL__ >= 904
+  check (HsPar _ _ e _) = check e
+  check (HsLamCase _ _ mg) = check mg
+  check HsRecSel{} = return True
+  check HsTypedBracket{} = notSupported "MetaHaskell"
+  check HsUntypedBracket{} = notSupported "MetaHaskell"
+#else
   check HsConLikeOut{} = return True
   check HsRecFld{} = return True
+  check (HsPar _ e) = check e
+  check (HsLamCase _ mg) = check mg
+  check HsBracket{} = notSupported "MetaHaskell"
+  check (HsTick _ _ e) = check e
+  check (HsBinTick _ _ _ e) = check e
+  check HsRnBracketOut{} = notSupported "MetaHaskell"
+  check HsTcBracketOut{} = notSupported "MetaHaskell"
+#endif
+#if __GLASGOW_HASKELL__ >= 904
+  check (HsLet _ _ bs _ e) = do
+#else
+  check (HsLet _ bs e) = do
+#endif
+    (l,vs) <- checkBind bs
+    r <- addVars vs `modifyCtxt` (check e)
+    return (r && l)
+         
   check HsOverLabel{} = return True
   check HsIPVar{} = notSupported "implicit parameters"
   check HsOverLit{} = return True  
-  check (HsTick _ _ e) = check e
-  check (HsBinTick _ _ _ e) = check e  
-  check (HsPar _ e) = check e
   check HsLit{} = return True
   check (OpApp _ e1 e2 e3) = and <$> mapM check [e1,e2,e3]
   check (HsLam _ mg) = check mg
-  check (HsLamCase _ mg) = check mg
   check (HsCase _ e1 e2) = (&&) <$> check e1 <*> check e2
   check (SectionL _ e1 e2) = (&&) <$> check e1 <*> check e2
   check (SectionR _ e1 e2) = (&&) <$> check e1 <*> check e2
   check (ExplicitTuple _ e _) = check e
-  check (HsLet _ bs e) = do
-    (l,vs) <- checkBind bs
-    r <- addVars vs `modifyCtxt` (check e)
-    return (r && l)
   check (NegApp _ e _) = check e
   check (ExplicitSum _ _ _ e) = check e
   check (HsMultiIf _ e) = check e
@@ -542,16 +573,21 @@
 #endif
   check RecordCon { rcon_flds = f} = check f
   check (ArithSeq _ _ e) = check e
-  check HsBracket{} = notSupported "MetaHaskell"
-  check HsRnBracketOut{} = notSupported "MetaHaskell"
-  check HsTcBracketOut{} = notSupported "MetaHaskell"
+#if __GLASGOW_HASKELL__ >= 906
+  check HsTypedSplice{} = notSupported "Template Haskell"
+  check HsUntypedSplice{} = notSupported "Template Haskell"
+#else
   check HsSpliceE{} = notSupported "Template Haskell"
+#endif
   check (HsProc _ p e) = mod `modifyCtxt` check e
     where mod c = addVars (getBV p) (stabilize StableArr c)
   check (HsStatic _ e) = check e
   check (HsDo _ _ e) = fst <$> checkBind e
   check (XExpr e) = check e
-#if __GLASGOW_HASKELL__ >= 808
+#if __GLASGOW_HASKELL__ >= 906
+  check (HsAppType _ e _ _) = check e
+  check (ExprWithTySig _ e _) = check e
+#elif __GLASGOW_HASKELL__ >= 808
   check (HsAppType _ e _) = check e
   check (ExprWithTySig _ e _) = check e
 #else
@@ -585,6 +621,11 @@
 instance Scope XXExprGhcTc where
   check (WrapExpr (HsWrap _ e)) = check e
   check (ExpansionExpr (HsExpanded _ e)) = check e
+#if __GLASGOW_HASKELL__ >= 904
+  check ConLikeTc{} = return True
+  check (HsTick _ e) = check e
+  check (HsBinTick _ _ e) = check e
+#endif
 #elif __GLASGOW_HASKELL__ >= 810
 instance Scope NoExtCon where
   check _ = return True
@@ -605,16 +646,25 @@
   check (HsCmdArrForm _ e1 _ _ e2) = (&&) <$> check e1 <*> check e2
   check (HsCmdApp _ e1 e2) = (&&) <$> check e1 <*> check e2
   check (HsCmdLam _ e) = check e
+#if __GLASGOW_HASKELL__ >= 904
+  check (HsCmdPar _ _ e _) = check e
+  check (HsCmdLamCase _ _ e) = check e  
+  check (HsCmdLet _ _ bs _ e) = do
+#else
   check (HsCmdPar _ e) = check e
-  check (HsCmdCase _ e1 e2) = (&&) <$> check e1 <*> check e2
-  check (HsCmdIf _ _ e1 e2 e3) = (&&) <$> ((&&) <$> check e1 <*> check e2) <*> check e3
+#if __GLASGOW_HASKELL__ >= 900
+  check (HsCmdLamCase _ e) = check e
+#endif
   check (HsCmdLet _ bs e) = do
+#endif
     (l,vs) <- checkBind bs
     r <- addVars vs `modifyCtxt` (check e)
     return (r && l)
+
+  check (HsCmdCase _ e1 e2) = (&&) <$> check e1 <*> check e2
+  check (HsCmdIf _ _ e1 e2 e3) = (&&) <$> ((&&) <$> check e1 <*> check e2) <*> check e3
 #if __GLASGOW_HASKELL__ >= 900
   check (XCmd (HsWrap _ e)) = check e
-  check (HsCmdLamCase _ e) = check e
 #else
   check (HsCmdWrap _ _ e) = check e
   check XCmd{} = return True
@@ -630,8 +680,15 @@
 instance Scope a => Scope (HsRecFields GhcTc a) where
   check HsRecFields {rec_flds = fs} = check fs
 
+
+
+#if __GLASGOW_HASKELL__ >= 904
+instance Scope b => Scope (HsFieldBind a b) where
+  check HsFieldBind{hfbRHS = a} = check a
+#else
 instance Scope b => Scope (HsRecField' a b) where
   check HsRecField{hsRecFieldArg = a} = check a
+#endif
 
 instance Scope (HsTupArg GhcTc) where
   check (Present _ e) = check e
@@ -641,9 +698,14 @@
 #endif
 
 instance Scope (HsBindLR GhcTc GhcTc) where
-  check AbsBinds {abs_binds = binds, abs_ev_vars  = ev} = mod `modifyCtxt` check binds
-    where mod c = c { stableTypes= stableTypes c `Set.union`
-                      Set.fromList (mapMaybe (isStableConstr . varType) ev)}
+#if __GLASGOW_HASKELL__ >= 904
+  check (XHsBindsLR AbsBinds {abs_binds = binds, abs_ev_vars  = ev})
+#else
+  check AbsBinds {abs_binds = binds, abs_ev_vars  = ev}
+#endif
+    = mod `modifyCtxt` check binds
+      where mod c = c { stableTypes= stableTypes c `Set.union`
+                        Set.fromList (mapMaybe (isStableConstr . varType) ev)}
   check FunBind{fun_matches= matches, fun_id = L _ v,
 #if __GLASGOW_HASKELL__ >= 900
                 fun_ext = wrapper} =
@@ -652,7 +714,7 @@
 #endif
       mod `modifyCtxt` check matches
     where mod c = c { stableTypes= stableTypes c `Set.union`
-                      Set.fromList (stableConstrFromWrapper wrapper)  `Set.union`
+                      Set.fromList (stableConstrFromWrapper' wrapper)  `Set.union`
                       Set.fromList (extractStableConstr (varType v))}
   check PatBind{pat_lhs = lhs, pat_rhs=rhs} = addVars (getBV lhs) `modifyCtxt` check rhs
   check VarBind{var_rhs = rhs} = check rhs
@@ -678,6 +740,15 @@
     _ ->  Nothing
 
 
+
+#if __GLASGOW_HASKELL__ >= 906
+stableConstrFromWrapper' :: (HsWrapper , a) -> [TyVar]
+stableConstrFromWrapper' (x , _) = stableConstrFromWrapper x
+#else
+stableConstrFromWrapper' :: HsWrapper -> [TyVar]
+stableConstrFromWrapper' = stableConstrFromWrapper
+#endif
+
 stableConstrFromWrapper :: HsWrapper -> [TyVar]
 stableConstrFromWrapper (WpCompose v w) = stableConstrFromWrapper v ++ stableConstrFromWrapper w
 stableConstrFromWrapper (WpEvLam v) = maybeToList $ isStableConstr (varType v)
@@ -704,9 +775,10 @@
 checkSCC' ::  Module -> AnnEnv -> SCC (LHsBindLR  GhcTc GhcTc, Set Var) -> TcM (Bool, [ErrorMsg])
 checkSCC' mod anEnv scc = do
   err <- liftIO (newIORef [])
-  res <- checkSCC err scc
+  let allowRec = AllowRecursion `Set.member` getAnn mod anEnv scc
+  res <- checkSCC allowRec err scc
   msgs <- liftIO (readIORef err)
-  let anns = getInternalAnn mod anEnv scc
+  let anns = getAnn mod anEnv scc
   if ExpectWarning `Set.member` anns 
     then if ExpectError `Set.member` anns
          then return (False,[(SevError, getSCCLoc scc, "Annotation to expect both warning and error is not allowed.")])
@@ -719,16 +791,15 @@
               else return (True,[])
          else return (res, msgs)
 
-
-getInternalAnn :: Module -> AnnEnv -> SCC (LHsBindLR  GhcTc GhcTc, Set Var) -> Set InternalAnn
-getInternalAnn mod anEnv scc =
+getAnn :: forall a . (Data a, Ord a) => Module -> AnnEnv -> SCC (LHsBindLR  GhcTc GhcTc, Set Var) -> Set a
+getAnn mod anEnv scc =
   case scc of
     (AcyclicSCC (_,vs)) -> Set.unions $ Set.map checkVar vs
     (CyclicSCC bs) -> Set.unions $ map (Set.unions . Set.map checkVar . snd) bs
-  where checkVar :: Var -> Set InternalAnn
+  where checkVar :: Var -> Set a
         checkVar v =
-          let anns = findAnns deserializeWithData anEnv (NamedTarget name) :: [InternalAnn]
-              annsMod = findAnns deserializeWithData anEnv (ModuleTarget mod) :: [InternalAnn]
+          let anns = findAnns deserializeWithData anEnv (NamedTarget name) :: [a]
+              annsMod = findAnns deserializeWithData anEnv (ModuleTarget mod) :: [a]
               name :: Name
               name = varName v
           in Set.fromList anns `Set.union` Set.fromList annsMod
@@ -739,13 +810,13 @@
 -- non-recursive definition or a group of (mutual) recursive
 -- definitions.
 
-checkSCC :: ErrorMsgsRef -> SCC (LHsBindLR  GhcTc GhcTc, Set Var) -> TcM Bool
-checkSCC errm (AcyclicSCC (b,_)) = setCtxt (emptyCtxt errm Nothing) (check b)
+checkSCC :: Bool -> ErrorMsgsRef -> SCC (LHsBindLR  GhcTc GhcTc, Set Var) -> TcM Bool
+checkSCC allowRec errm (AcyclicSCC (b,_)) = setCtxt (emptyCtxt errm Nothing allowRec) (check b)
 
-checkSCC errm (CyclicSCC bs) = (fmap and (mapM check' bs'))
+checkSCC allowRec errm (CyclicSCC bs) = (fmap and (mapM check' bs'))
   where bs' = map fst bs
         vs = foldMap snd bs
-        check' b@(L l _) = setCtxt (emptyCtxt errm (Just (vs,getLocAnn' l))) (checkRec b)
+        check' b@(L l _) = setCtxt (emptyCtxt errm (Just (vs,getLocAnn' l)) allowRec) (checkRec b)
 
 -- | Stabilizes the given context, i.e. remove all non-stable types
 -- and any tick. This is performed on checking 'box', 'arr' and
@@ -767,8 +838,8 @@
 getScope  :: GetCtxt => Var -> VarScope
 getScope v =
   case ?ctxt of
-    Ctxt{recDef = Just (vs,_), earlier = e}
-      | v `Set.member` vs ->
+    Ctxt{recDef = Just (vs,_), earlier = e, allowRecursion = allowRec} | v `Set.member` vs ->
+     if allowRec then Visible else
         case e of
           Right _ -> Visible
           Left NoDelay -> Hidden ("The (mutually) recursive call to " <> ppr v <> " must occur in the scope of a delay")
@@ -776,7 +847,7 @@
                             <> "There is a delay, but its scope is interrupted by " <> tickHidden hr <> ".")
     _ ->  case Map.lookup v (hidden ?ctxt) of
             Just (Stabilize (StableRec rv)) ->
-              if (isStable (stableTypes ?ctxt) (varType v)) then Visible
+              if (isStable (stableTypes ?ctxt) (varType v)) || allowRecursion ?ctxt then Visible
               else Hidden ("Variable " <> ppr v <> " is no longer in scope:" $$
                        "It appears in a local recursive definition (at " <> ppr rv <> ")"
                        $$ "and is of type " <> ppr (varType v) <> ", which is not stable.")
@@ -828,7 +899,9 @@
 isPrimExpr (L _ e) = isPrimExpr' e where
   isPrimExpr' :: GetCtxt => HsExpr GhcTc -> Maybe (Prim,Var)
   isPrimExpr' (HsVar _ (L _ v)) = fmap (,v) (isPrim v)
-#if __GLASGOW_HASKELL__ >= 808
+#if __GLASGOW_HASKELL__ >= 906
+  isPrimExpr' (HsAppType _ e _ _) = isPrimExpr e
+#elif __GLASGOW_HASKELL__ >= 808
   isPrimExpr' (HsAppType _ e _) = isPrimExpr e
 #else
   isPrimExpr' (HsAppType _ e)   = isPrimExpr e
@@ -844,9 +917,15 @@
   isPrimExpr' (XExpr (ExpansionExpr (HsExpanded _ e))) = isPrimExpr' e
   isPrimExpr' (HsPragE _ _ e) = isPrimExpr e
 #endif
+#if __GLASGOW_HASKELL__ < 904
   isPrimExpr' (HsTick _ _ e) = isPrimExpr e
-  isPrimExpr' (HsBinTick _ _ _ e) = isPrimExpr e  
+  isPrimExpr' (HsBinTick _ _ _ e) = isPrimExpr e
   isPrimExpr' (HsPar _ e) = isPrimExpr e
+#else
+  isPrimExpr' (XExpr (HsTick _ e)) = isPrimExpr e
+  isPrimExpr' (XExpr (HsBinTick _ _ e)) = isPrimExpr e
+  isPrimExpr' (HsPar _ _ e _) = isPrimExpr e
+#endif
 
   isPrimExpr' _ = Nothing
 
diff --git a/src/Rattus/Plugin/StableSolver.hs b/src/Rattus/Plugin/StableSolver.hs
--- a/src/Rattus/Plugin/StableSolver.hs
+++ b/src/Rattus/Plugin/StableSolver.hs
@@ -37,8 +37,9 @@
 
 import Data.Set (Set)
 import qualified Data.Set as Set
-
-
+#if __GLASGOW_HASKELL__ >= 904
+import GHC.Types.Unique.FM
+#endif
 
 
 
@@ -48,6 +49,9 @@
   { tcPluginInit = return ()
   , tcPluginSolve = \ () -> stableSolver
   , tcPluginStop = \ () -> return ()
+#if __GLASGOW_HASKELL__ >= 904
+  , tcPluginRewrite = \ () -> emptyUFM
+#endif
   }
 
 
@@ -63,8 +67,14 @@
   | isStable c ty = Just (wrap cl ty, ct)
   | otherwise = Nothing
 
+#if __GLASGOW_HASKELL__ >= 904
+stableSolver :: EvBindsVar -> [Ct] -> [Ct] -> TcPluginM TcPluginSolveResult
+stableSolver _ given wanted = do
+#else
 stableSolver :: [Ct] -> [Ct] -> [Ct] -> TcPluginM TcPluginResult
 stableSolver given _derived wanted = do
+#endif
+
   let chSt = concatMap filterCt wanted
   let haveSt = Set.fromList $ concatMap (filterTypeVar . fst) $ concatMap filterCt given
   case mapM (solveStable haveSt) chSt of
diff --git a/src/Rattus/Plugin/Utils.hs b/src/Rattus/Plugin/Utils.hs
--- a/src/Rattus/Plugin/Utils.hs
+++ b/src/Rattus/Plugin/Utils.hs
@@ -22,6 +22,13 @@
   getAlt,
   splitForAllTys')
   where
+#if __GLASGOW_HASKELL__ >= 906
+import GHC.Builtin.Types.Prim
+import GHC.Tc.Utils.TcType
+#endif
+#if __GLASGOW_HASKELL__ >= 904
+import qualified GHC.Data.Strict as Strict
+#endif  
 #if __GLASGOW_HASKELL__ >= 902
 import GHC.Utils.Logger
 #endif
@@ -36,6 +43,8 @@
 import MonadUtils
 #endif
 
+
+
 import Prelude hiding ((<>))
 
 import Data.Set (Set)
@@ -50,6 +59,11 @@
 isType _ = False
 
 
+#if __GLASGOW_HASKELL__ >= 906
+isFunTyCon = isArrowTyCon
+repSplitAppTys = splitAppTysNoView
+#endif
+
 #if __GLASGOW_HASKELL__ >= 902
 printMessage :: (HasDynFlags m, MonadIO m, HasLogger m) =>
                 Severity -> SrcSpan -> SDoc -> m ()
@@ -58,7 +72,15 @@
                 Severity -> SrcSpan -> MsgDoc -> m ()
 #endif
 printMessage sev loc doc = do
-#if __GLASGOW_HASKELL__ >= 902
+#if __GLASGOW_HASKELL__ >= 906
+  logger <- getLogger
+  liftIO $ putLogMsg logger (logFlags logger)
+    (MCDiagnostic sev (if sev == SevError then ErrorWithoutFlag else WarningWithoutFlag) Nothing) loc doc
+#elif __GLASGOW_HASKELL__ >= 904
+  logger <- getLogger
+  liftIO $ putLogMsg logger (logFlags logger)
+    (MCDiagnostic sev (if sev == SevError then ErrorWithoutFlag else WarningWithoutFlag)) loc doc
+#elif __GLASGOW_HASKELL__ >= 902
   dflags <- getDynFlags
   logger <- getLogger
   liftIO $ putLogMsg logger dflags NoReason sev loc doc
@@ -274,14 +296,16 @@
 
 mkSysLocalFromExpr :: MonadUnique m => FastString -> CoreExpr -> m Id
 #if __GLASGOW_HASKELL__ >= 900
-mkSysLocalFromExpr lit e = mkSysLocalM lit One (exprType e)
+mkSysLocalFromExpr lit e = mkSysLocalM lit oneDataConTy (exprType e)
 #else
 mkSysLocalFromExpr lit e = mkSysLocalM lit (exprType e)
 #endif
 
 
 fromRealSrcSpan :: RealSrcSpan -> SrcSpan
-#if __GLASGOW_HASKELL__ >= 900
+#if __GLASGOW_HASKELL__ >= 904
+fromRealSrcSpan span = RealSrcSpan span Strict.Nothing
+#elif __GLASGOW_HASKELL__ >= 900
 fromRealSrcSpan span = RealSrcSpan span Nothing
 #else
 fromRealSrcSpan span = RealSrcSpan span
diff --git a/src/Rattus/Strict.hs b/src/Rattus/Strict.hs
--- a/src/Rattus/Strict.hs
+++ b/src/Rattus/Strict.hs
@@ -1,3 +1,5 @@
+{-# OPTIONS -fplugin=Rattus.Plugin #-}
+
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE TypeOperators #-}
@@ -10,6 +12,8 @@
 
 module Rattus.Strict
   ( List(..),
+    init',
+    listDelay,
     reverse',
     (+++),
     listToMaybe',
@@ -22,12 +26,33 @@
   )where
 
 import Data.VectorSpace
+import Rattus.Primitives
+import Rattus.Plugin.Annotation
 
 infixr 2 :*
 infixr 8 :!
 
 -- | Strict list type.
 data List a = Nil | !a :! !(List a)
+
+
+{-# ANN module Rattus #-}
+-- All recursive functions in this module are defined by structural
+-- induction on a strict type.
+{-# ANN module AllowRecursion #-}
+
+-- | Turns a list of delayed computations into a delayed computation
+-- that produces a list of values.
+listDelay :: List (O a) -> O (List a)
+listDelay Nil = delay Nil
+listDelay (x :! xs) = let xs' = listDelay xs in delay (adv x :! adv xs')
+
+-- | Remove the last element from a list if there is one, otherwise
+-- return 'Nil'.
+init' :: List a -> List a
+init' Nil = Nil
+init' (_ :! Nil) = Nil
+init' (x :! xs) = x :! init' xs
 
 -- | Reverse a list.
 reverse' :: List a -> List a
diff --git a/src/Rattus/Yampa.hs b/src/Rattus/Yampa.hs
--- a/src/Rattus/Yampa.hs
+++ b/src/Rattus/Yampa.hs
@@ -61,7 +61,7 @@
 
 -- | Compute the integral of a signal. The first argument is the
 -- offset.
-integral :: (Stable a, VectorSpace a s) => a -> SF a a
+integral :: (Stable a, VectorSpace a s, Fractional s) => a -> SF a a
 integral acc = SF sf'
   where sf' t a = let acc' = acc ^+^ (realToFrac t *^ a)
                   in (delay (integral acc') :* acc')
