diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,6 +1,8 @@
 # README
 --------
 
+[![Build Status](https://travis-ci.org/turion/rhine.svg?branch=master)](https://travis-ci.org/turion/rhine)
+
 Rhine is a library for synchronous and asynchronous Functional Reactive Programming (FRP).
 It separates the aspects of clocking, scheduling and resampling
 from each other, and ensures clock-safety on the type level.
diff --git a/examples/test/Test.hs b/examples/test/Test.hs
deleted file mode 100644
--- a/examples/test/Test.hs
+++ /dev/null
@@ -1,38 +0,0 @@
-{-# LANGUAGE Arrows           #-}
-{-# LANGUAGE DataKinds        #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE TypeFamilies     #-}
-
-
--- rhine
-import FRP.Rhine
-import FRP.Rhine.Clock.Realtime.Millisecond
-import FRP.Rhine.Schedule.Concurrently
-
--- | Calculates and prints the rounding errors that accumulate
---   when calculating the time since the start of the simulation
---   via an Euler integral.
-showRoundingError
-  :: Diff (TimeDomainOf cl) ~ Double
-  => String -> SyncSF IO cl () ()
-showRoundingError clName = proc () -> do
-  correct   <- timeInfoOf sinceStart -< ()
-  simulated <- arr_ 1 >>> integral   -< ()
-  liftS putStrLn -<
-    "Clock " ++ clName
-    ++ " ticks at time "     ++ show correct
-    ++ " and simulates "     ++ show simulated
-    ++ " => rounding error " ++ show (correct - simulated)
-
--- | Show the rounding error for the 1000 milliseconds clock.
-showREMS1000 :: SyncSF IO (Millisecond 1000) () ()
-showREMS1000 = showRoundingError "Millisecond 1000"
-
--- | Show the rounding error for the 350 milliseconds clock.
-showREMS350 :: SyncSF IO (Millisecond 350) () ()
-showREMS350 = showRoundingError "Millisecond 350"
-
--- | The main program runs both synchronous signal functions in parallel,
---   using a concurrent (GHC threads) schedule.
-main :: IO ()
-main = flow $ showREMS350 @@ waitClock **@ concurrently @** showREMS1000 @@ waitClock
diff --git a/rhine.cabal b/rhine.cabal
--- a/rhine.cabal
+++ b/rhine.cabal
@@ -1,6 +1,6 @@
 name:                rhine
 
-version:             0.1.1.0
+version:             0.2.0.0
 
 synopsis: Functional Reactive Programming with type-level clocks
 
@@ -44,7 +44,7 @@
 source-repository this
   type:     git
   location: git@github.com:turion/rhine.git
-  tag:      v0.1.1.0
+  tag:      v0.2.0.0
 
 
 library
@@ -84,7 +84,7 @@
 
   -- Other library packages from which modules are imported.
   build-depends:       base         >= 4.7   && < 5
-                    ,  dunai        == 0.1.1.*
+                    ,  dunai        == 0.2.0.*
                     ,  transformers >= 0.4   && < 0.6
                     ,  time         >= 1.6   && < 1.7
                     ,  free         >= 4.12  && < 4.13
@@ -98,19 +98,12 @@
   -- Base language which the package is written in.
   default-language:    Haskell2010
 
-executable test
-  hs-source-dirs:      examples/test
-  main-is:             Test.hs
-  ghc-options:         -Wall -threaded -rtsopts -with-rtsopts=-N
-  build-depends:       base  >= 4.8     && <5
-                     , rhine
-  default-language:    Haskell2010
 
 executable HelloWorld
   hs-source-dirs:      examples
   main-is:             HelloWorld.hs
   ghc-options:         -Wall -threaded -rtsopts -with-rtsopts=-N
-  build-depends:       base  >= 4.8     && <5
+  build-depends:       base  >= 4.7     && <5
                      , rhine
   default-language:    Haskell2010
 
@@ -118,6 +111,6 @@
   hs-source-dirs:      examples
   main-is:             Demonstration.hs
   ghc-options:         -Wall -threaded -rtsopts -with-rtsopts=-N
-  build-depends:       base  >= 4.8     && <5
+  build-depends:       base  >= 4.7     && <5
                      , rhine
   default-language:    Haskell2010
diff --git a/src/FRP/Rhine/Clock.hs b/src/FRP/Rhine/Clock.hs
--- a/src/FRP/Rhine/Clock.hs
+++ b/src/FRP/Rhine/Clock.hs
@@ -130,8 +130,8 @@
   , monadMorphism :: forall a . m1 a -> m2 a
   }
 
-instance (Monad m1, Monad m2, Clock m1 a)
-      => Clock m2 (HoistClock m1 m2 a) where
+instance (Monad m1, Monad m2, Clock m1 cl)
+      => Clock m2 (HoistClock m1 m2 cl) where
   type TimeDomainOf (HoistClock m1 m2 cl) = TimeDomainOf cl
   type Tag          (HoistClock m1 m2 cl) = Tag          cl
   startClock HoistClock {..} = do
diff --git a/src/FRP/Rhine/Clock/Realtime/Audio.hs b/src/FRP/Rhine/Clock/Realtime/Audio.hs
--- a/src/FRP/Rhine/Clock/Realtime/Audio.hs
+++ b/src/FRP/Rhine/Clock/Realtime/Audio.hs
@@ -22,14 +22,11 @@
 import Data.Time.Clock
 
 -- transformers
--- TODO Delete as soon as dunai is updated
-import Control.Monad.Trans.Class (lift)
 import Control.Monad.IO.Class
 
 
 -- dunai
 import Control.Monad.Trans.MSF.Except
-  hiding (once, once_) -- TODO Delete with dunai 0.1.2
 
 -- rhine
 import FRP.Rhine
@@ -155,11 +152,3 @@
   { unscaledClock = PureAudioClock
   , rescale       = double2Float
 }
-
--- ** To be ported to @dunai@
-
-once :: Monad m => (a -> m e) -> MSFExcept m a b e
-once f = try $ arrM (lift . f) >>> throwS
--- TODO Delete once dunai is updated
-once_ :: Monad m => m e -> MSFExcept m a b e
-once_ = once . const
diff --git a/src/FRP/Rhine/Clock/Select.hs b/src/FRP/Rhine/Clock/Select.hs
--- a/src/FRP/Rhine/Clock/Select.hs
+++ b/src/FRP/Rhine/Clock/Select.hs
@@ -10,8 +10,7 @@
 import FRP.Rhine
 
 -- dunai
--- import Data.MonadicStreamFunction.Async (concatS)
--- TODO dunai 0.1.2
+import Data.MonadicStreamFunction.Async (concatS)
 
 -- base
 import Data.Maybe (catMaybes, maybeToList)
@@ -27,7 +26,7 @@
 
 
 instance (Monad m, Clock m cl) => Clock m (SelectClock cl a) where
-  type TimeDomainOf (SelectClock cl _) = TimeDomainOf cl
+  type TimeDomainOf (SelectClock cl a) = TimeDomainOf cl
   type Tag          (SelectClock cl a) = a
   startClock SelectClock {..} = do
     (runningClock, initialTime) <- startClock mainClock
@@ -56,15 +55,8 @@
             , (time, ) . Right <$> select subClock2 tag ]
       return (runningSelectClocks, initialTime)
 
--- ** To be ported to @dunai@
 
-concatS :: Monad m => MStream m [b] -> MStream m b
-concatS msf = MSF $ \_ -> tick msf []
-  where
-    tick msf (b:bs) = return (b, MSF $ \_ -> tick msf bs)
-    tick msf []     = do
-      (bs, msf') <- unMSF msf ()
-      tick msf' bs
-
+-- | Helper function that runs an 'MSF' with 'Maybe' output
+--   until it returns a value.
 filterS :: Monad m => MSF m () (Maybe b) -> MSF m () b
 filterS = concatS . (>>> arr maybeToList)
diff --git a/src/FRP/Rhine/Clock/Step.hs b/src/FRP/Rhine/Clock/Step.hs
--- a/src/FRP/Rhine/Clock/Step.hs
+++ b/src/FRP/Rhine/Clock/Step.hs
@@ -11,6 +11,8 @@
 -- base
 import GHC.TypeLits
 
+-- dunai
+import Data.MonadicStreamFunction.Async (concatS)
 
 -- rhine
 import FRP.Rhine
@@ -49,15 +51,3 @@
         k <- arr (+1) <<< count -< ()
         returnA                 -< [ (k, Left  ()) | k `mod` n1 == 0 ]
                                 ++ [ (k, Right ()) | k `mod` n2 == 0 ]
-
-
--- * To be ported to dunai
-
--- TODO Will be in dunai
-concatS :: Monad m => MSF m () [b] -> MSF m () b
-concatS msf = MSF $ \_ -> tick msf []
-  where
-    tick msf (b:bs) = return (b, MSF $ \_ -> tick msf bs)
-    tick msf []     = do
-      (bs, msf') <- unMSF msf ()
-      tick msf' bs
diff --git a/src/FRP/Rhine/SyncSF.hs b/src/FRP/Rhine/SyncSF.hs
--- a/src/FRP/Rhine/SyncSF.hs
+++ b/src/FRP/Rhine/SyncSF.hs
@@ -1,7 +1,8 @@
-{-# LANGUAGE Arrows          #-}
-{-# LANGUAGE RankNTypes      #-}
-{-# LANGUAGE RecordWildCards #-}
-{-# LANGUAGE TypeFamilies    #-}
+{-# LANGUAGE Arrows           #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE RankNTypes       #-}
+{-# LANGUAGE RecordWildCards  #-}
+{-# LANGUAGE TypeFamilies     #-}
 
 module FRP.Rhine.SyncSF where
 
@@ -163,25 +164,69 @@
   => SyncSF m cl v v
 derivative = derivativeFrom zeroVector
 
+-- | A weighted moving average signal function.
+--   The output is the average of the first input,
+--   weighted by the second input
+--   (which is assumed to be always between 0 and 1).
+--   The weight is applied to the average of the last tick,
+--   so a weight of 1 simply repeats the past value unchanged,
+--   whereas a weight of 0 outputs the current value.
+weightedAverageFrom
+  :: ( Monad m, VectorSpace v
+     , Groundfield v ~ Diff (TimeDomainOf cl))
+  => v -- ^ The initial position
+  -> SyncSF m cl (v, Groundfield v) v
+weightedAverageFrom v0 = feedback v0 $ proc ((v, weight), vAvg) -> do
+  let
+    vAvg' = weight *^ vAvg ^+^ (1 - weight) *^ v
+  returnA -< (vAvg', vAvg')
 
--- | An average, or low pass. It will average out, or filter,
+-- | An exponential moving average, or low pass.
+--   It will average out, or filter,
 --   all features below a given time scale.
 averageFrom
   :: ( Monad m, VectorSpace v
+     , Floating (Groundfield v)
      , Groundfield v ~ Diff (TimeDomainOf cl))
   => v -- ^ The initial position
   -> Diff (TimeDomainOf cl) -- ^ The time scale on which the signal is averaged
   -> SyncSF m cl v v
-averageFrom v0 t = feedback v0 $ proc (v, vAvg) -> do
+averageFrom v0 t = proc v -> do
   TimeInfo {..} <- timeInfo -< ()
-  let vAvg' = (v ^* sinceTick ^+^ vAvg ^* t) ^/ (sinceTick + t)
-  returnA                   -< (vAvg', vAvg')
+  let
+    weight = exp $ - (sinceTick / t)
+  weightedAverageFrom v0    -< (v, weight)
 
 
 -- | An average, or low pass, initialised to zero.
 average
   :: ( Monad m, VectorSpace v
+     , Floating (Groundfield v)
      , Groundfield v ~ Diff (TimeDomainOf cl))
   => Diff (TimeDomainOf cl) -- ^ The time scale on which the signal is averaged
   -> SyncSF m cl v v
 average = averageFrom zeroVector
+
+-- | A linearised version of 'averageFrom'.
+--   It is more efficient, but only accurate
+--   if the supplied time scale is much bigger
+--   than the average time difference between two ticks.
+averageLinFrom
+  :: ( Monad m, VectorSpace v
+     , Groundfield v ~ Diff (TimeDomainOf cl))
+  => v -- ^ The initial position
+  -> Diff (TimeDomainOf cl) -- ^ The time scale on which the signal is averaged
+  -> SyncSF m cl v v
+averageLinFrom v0 t = proc v -> do
+  TimeInfo {..} <- timeInfo -< ()
+  let
+    weight = t / (sinceTick + t)
+  weightedAverageFrom v0    -< (v, weight)
+
+-- | Linearised version of 'average'.
+averageLin
+  :: ( Monad m, VectorSpace v
+     , Groundfield v ~ Diff (TimeDomainOf cl))
+  => Diff (TimeDomainOf cl) -- ^ The time scale on which the signal is averaged
+  -> SyncSF m cl v v
+averageLin = averageLinFrom zeroVector
diff --git a/src/FRP/Rhine/SyncSF/Except.hs b/src/FRP/Rhine/SyncSF/Except.hs
--- a/src/FRP/Rhine/SyncSF/Except.hs
+++ b/src/FRP/Rhine/SyncSF/Except.hs
@@ -34,8 +34,7 @@
 -- | Within the same tick, perform a monadic action,
 --   and immediately throw the value as an exception.
 once :: Monad m => (a -> m e) -> SyncExcept m cl a b e
--- once f = MSFE.once $ lift . f -- TODO dunai 0.1.2
-once f = try $ arrMSync (lift . f) >>> throwS
+once f = MSFE.once $ lift . f
 
 -- | A variant of |once| without input.
 once_ :: Monad m => m e -> SyncExcept m cl a b e
@@ -54,17 +53,7 @@
 throwOn e = proc b -> throwOn' -< (b, e)
 
 
--- ** Will be in dunai-0.1.2
-
 -- | Advances a single tick with the given Kleisli arrow,
 --   and then throws an exception.
 step :: Monad m => (a -> m (b, e)) -> SyncExcept m cl a b e
-step f = try $ proc a -> do
-  n      <- count               -< ()
-  (b, e) <- arrMSync (lift . f) -< a
-  _      <- throwOn'            -< (n > (1 :: Int), e)
-  returnA                       -< b
-
--- | Immediately throw the current input as an exception.
-currentInput :: Monad m => SyncExcept m cl e b e
-currentInput = try throwS
+step f = MSFE.step $ lift . f
