diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
 # Revision history for automaton
 
-## 0.1.0.0
+## 1.4
 
-* Initial version ;)
+* Added `Data.Automaton.Trans.Accum`
+* Added `unfold_`
+* Backwards compatible to 1.3, but to keep version numbers in sync with rhine, the automaton version has also been bumped
+
+## 1.3
+
+* Initial version
diff --git a/automaton.cabal b/automaton.cabal
--- a/automaton.cabal
+++ b/automaton.cabal
@@ -1,11 +1,11 @@
 cabal-version: 3.0
 name: automaton
-version: 1.3
+version: 1.4
 synopsis: Effectful streams and automata in initial encoding
 description:
   Effectful streams have an internal state and a step function.
   Varying the effect type, this gives many different useful concepts:
-  For example with a reader effect, it results in automata/transducers/state machines.
+  For example with a reader effect, it results in automata (a.k.a transducers or state machines).
 
 license: MIT
 license-file: LICENSE
@@ -24,7 +24,7 @@
 source-repository this
   type: git
   location: https://github.com/turion/rhine.git
-  tag: v1.3
+  tag: v1.4
 
 common opts
   build-depends:
@@ -65,6 +65,7 @@
   exposed-modules:
     Data.Automaton
     Data.Automaton.Final
+    Data.Automaton.Trans.Accum
     Data.Automaton.Trans.Except
     Data.Automaton.Trans.Maybe
     Data.Automaton.Trans.RWS
@@ -93,6 +94,7 @@
   other-modules:
     Automaton
     Automaton.Except
+    Automaton.Trans.Accum
     Stream
 
   build-depends:
diff --git a/src/Data/Automaton.hs b/src/Data/Automaton.hs
--- a/src/Data/Automaton.hs
+++ b/src/Data/Automaton.hs
@@ -111,6 +111,16 @@
   Automaton m a b
 unfoldM state step = Automaton $! Stateful $! StreamT {state, step = \s -> ReaderT $ \a -> step a s}
 
+-- | Like 'unfold', but output the current state.
+unfold_ ::
+  (Applicative m) =>
+  -- | The initial state
+  s ->
+  -- | The step function
+  (a -> s -> s) ->
+  Automaton m a s
+unfold_ state step = unfold state $ \a s -> let s' = step a s in Result s' s'
+
 instance (Eq s, Floating s, VectorSpace v s, Applicative m) => VectorSpace (Automaton m a v) (Automaton m a s) where
   zeroVector = Automaton zeroVector
   Automaton s *^ Automaton v = coerce $ s *^ v
diff --git a/src/Data/Automaton/Trans/Accum.hs b/src/Data/Automaton/Trans/Accum.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Automaton/Trans/Accum.hs
@@ -0,0 +1,60 @@
+{- | Handle a global 'AccumT' layer in an 'Automaton'.
+
+A global accumulation state can be hidden by an automaton by making it an internal state.
+-}
+module Data.Automaton.Trans.Accum (
+  module Control.Monad.Trans.Accum,
+  accumS,
+  runAccumS,
+  runAccumS_,
+  runAccumS__,
+)
+where
+
+-- base
+import Control.Arrow (arr, returnA, (>>>))
+
+-- transformers
+import Control.Monad.Trans.Accum
+
+-- automaton
+import Data.Automaton (Automaton, feedback, withAutomaton)
+import Data.Stream.Result (Result (..))
+
+{- | Convert from explicit states to the 'AccumT' monad transformer.
+
+The original automaton is interpreted to take the current accumulated state as input and return the log to be appended as output.
+
+This is the opposite of 'runAccumS'.
+-}
+accumS :: (Functor m, Monad m) => Automaton m (w, a) (w, b) -> Automaton (AccumT w m) a b
+accumS = withAutomaton $ \f a -> AccumT $ \w ->
+  (\(Result s (w', b)) -> (Result s b, w'))
+    <$> f (w, a)
+
+{- | Make the accumulation transition in 'AccumT' explicit as 'Automaton' inputs and outputs.
+
+This is the opposite of 'accumS'.
+-}
+runAccumS :: (Functor m, Monad m) => Automaton (AccumT w m) a b -> Automaton m (w, a) (w, b)
+runAccumS = withAutomaton $ \f (w, a) ->
+  (\(Result s b, w') -> Result s (w', b))
+    <$> runAccumT (f a) w
+
+{- | Convert global accumulation state to internal state of an 'Automaton'.
+
+The current state is output on every step.
+-}
+runAccumS_ ::
+  (Functor m, Monoid w, Monad m) =>
+  -- | An automaton with a global accumulation state effect
+  Automaton (AccumT w m) a b ->
+  Automaton m a (w, b)
+runAccumS_ automaton = feedback mempty $ proc (a, wState) -> do
+  (wAdd, b) <- runAccumS automaton -< (wState, a)
+  let wState' = wState <> wAdd
+  returnA -< ((wState', b), wState')
+
+-- | Like 'runAccumS_', but don't output the current accum.
+runAccumS__ :: (Functor m, Monoid w, Monad m) => Automaton (AccumT w m) a b -> Automaton m a b
+runAccumS__ automaton = runAccumS_ automaton >>> arr snd
diff --git a/test/Automaton.hs b/test/Automaton.hs
--- a/test/Automaton.hs
+++ b/test/Automaton.hs
@@ -28,6 +28,7 @@
 
 -- automaton
 import Automaton.Except
+import Automaton.Trans.Accum
 import Data.Automaton
 import Data.Automaton.Final
 import Data.Automaton.Trans.Maybe
@@ -70,6 +71,7 @@
     , testCase "sumN" $ runIdentity (embed (arr (const (1 :: Integer)) >>> sumN) [(), (), ()]) @?= [1, 2, 3]
     , testCase "lastS" $ runIdentity (embed (lastS 0) [Nothing, Just 10]) @?= [0, 10]
     , Automaton.Except.tests
+    , Automaton.Trans.Accum.tests
     ]
 
 inMaybe :: Automaton Maybe (Maybe a) a
diff --git a/test/Automaton/Except.hs b/test/Automaton/Except.hs
--- a/test/Automaton/Except.hs
+++ b/test/Automaton/Except.hs
@@ -9,7 +9,7 @@
 -- tasty-hunit
 import Test.Tasty.HUnit (testCase, (@?=))
 
--- rhine
+-- automaton
 import Data.Automaton (embed)
 import Data.Automaton.Trans.Except (safe, safely, step)
 
diff --git a/test/Automaton/Trans/Accum.hs b/test/Automaton/Trans/Accum.hs
new file mode 100644
--- /dev/null
+++ b/test/Automaton/Trans/Accum.hs
@@ -0,0 +1,20 @@
+module Automaton.Trans.Accum where
+
+-- base
+import Control.Monad.Identity (Identity (runIdentity))
+import Data.Monoid (Sum (..))
+
+-- transformers
+import Control.Monad.Trans.Accum (add, look)
+
+-- tasty
+import Test.Tasty (testGroup)
+
+-- tasty-hunit
+import Test.Tasty.HUnit (testCase, (@?=))
+
+-- automaton
+import Data.Automaton
+import Data.Automaton.Trans.Accum (runAccumS_)
+
+tests = testGroup "Trans.Accum" [testCase "runAccumS_" $ runIdentity (embed (runAccumS_ (constM (add (Sum 1) >> look))) (replicate 5 ())) @?= (\n -> (n, n)) <$> [1, 2, 3, 4, 5]]
