diff --git a/cqrs.cabal b/cqrs.cabal
--- a/cqrs.cabal
+++ b/cqrs.cabal
@@ -1,5 +1,5 @@
 Name:                cqrs
-Version:             0.2.1
+Version:             0.3.0
 Synopsis:            Command-Query Responsibility Segregation
 Description:         Haskell implementation of the CQRS architectural pattern.
   An SQLite3-based backend is included.
@@ -27,13 +27,13 @@
                        OverloadedStrings
                        Rank2Types
                        ScopedTypeVariables
-                       TemplateHaskell
   ghc-options:         -Wall
   hs-source-dirs:      src
   Exposed-modules:     Data.CQRS
                        Data.CQRS.Aggregate
                        Data.CQRS.AggregateRef
                        Data.CQRS.Event
+                       Data.CQRS.Eventable
                        Data.CQRS.EventStore
                        Data.CQRS.EventStore.Sqlite3
                        Data.CQRS.GUID
diff --git a/src/Data/CQRS.hs b/src/Data/CQRS.hs
--- a/src/Data/CQRS.hs
+++ b/src/Data/CQRS.hs
@@ -4,6 +4,7 @@
         ( module Data.CQRS.Aggregate
         , module Data.CQRS.AggregateRef
         , module Data.CQRS.Event
+        , module Data.CQRS.Eventable
         , module Data.CQRS.GUID
         , module Data.CQRS.Transaction
         ) where
@@ -11,5 +12,6 @@
 import Data.CQRS.Aggregate
 import Data.CQRS.AggregateRef
 import Data.CQRS.Event
+import Data.CQRS.Eventable
 import Data.CQRS.GUID
 import Data.CQRS.Transaction
diff --git a/src/Data/CQRS/Event.hs b/src/Data/CQRS/Event.hs
--- a/src/Data/CQRS/Event.hs
+++ b/src/Data/CQRS/Event.hs
@@ -6,10 +6,8 @@
 
 import Data.ByteString (ByteString)
 
--- | Event class for applying events to aggregates.
-class Event e a | e -> a where
-  -- | Apply an event to the aggregate and return the updated aggregate.
-  applyEvent :: e -> a -> a
+-- | Event class.
+class Event e where
   -- | Encode event into a strict ByteString.
   encodeEvent :: e -> ByteString
   -- | Decode event from a strict ByteString. To avoid corrupt
diff --git a/src/Data/CQRS/Eventable.hs b/src/Data/CQRS/Eventable.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/CQRS/Eventable.hs
@@ -0,0 +1,9 @@
+-- | Eventable type class.
+module Data.CQRS.Eventable
+       ( Eventable(..)
+       ) where
+
+-- | Type class for applying events to aggregates.
+class Eventable a e | a -> e where
+  -- | Apply an event to the aggregate and return the updated aggregate.
+  applyEvent :: e -> a -> a
diff --git a/src/Data/CQRS/Internal/AggregateRef.hs b/src/Data/CQRS/Internal/AggregateRef.hs
--- a/src/Data/CQRS/Internal/AggregateRef.hs
+++ b/src/Data/CQRS/Internal/AggregateRef.hs
@@ -13,7 +13,7 @@
 import Control.Monad (liftM)
 import Control.Monad.IO.Class (MonadIO, liftIO)
 import Data.CQRS.GUID (GUID)
-import Data.CQRS.Event (Event(..))
+import Data.CQRS.Eventable (Eventable(..))
 import Data.IORef (IORef, modifyIORef, newIORef, readIORef)
 import Data.Typeable (Typeable)
 
@@ -35,7 +35,7 @@
   return $ AggregateRef a' e' guid originatingVersion snapshotVersion
 
 -- | Publish event to aggregate.
-publishEvent :: (MonadIO m, Event e a) => AggregateRef a e -> e -> m ()
+publishEvent :: (MonadIO m, Eventable a e) => AggregateRef a e -> e -> m ()
 publishEvent aggregateRef event = liftIO $ do
   -- Apply event to aggregate state.
   modifyIORef (arValue aggregateRef) $ applyEvent event
diff --git a/src/Data/CQRS/Transaction.hs b/src/Data/CQRS/Transaction.hs
--- a/src/Data/CQRS/Transaction.hs
+++ b/src/Data/CQRS/Transaction.hs
@@ -15,6 +15,7 @@
 import           Data.CQRS.Internal.AggregateRef (AggregateRef, mkAggregateRef)
 import qualified Data.CQRS.Internal.AggregateRef as AR
 import           Data.CQRS.Event (Event(..))
+import           Data.CQRS.Eventable (Eventable(..))
 import           Data.CQRS.EventStore (EventStore, withTransaction)
 import qualified Data.CQRS.EventStore as ES
 import           Data.CQRS.GUID (GUID)
@@ -31,7 +32,7 @@
 
 -- Existential wrapper for AggregateRef.
 data BoxedAggregateRef e =
-  forall a . (Typeable a, Typeable e, Event e a, Default a, Aggregate a) => BoxedAggregateRef (AggregateRef a e)
+  forall a . (Typeable a, Typeable e, Event e, Default a, Aggregate a, Eventable a e) => BoxedAggregateRef (AggregateRef a e)
 
 -- | Transaction monad itself.
 type Transaction e = StateT (TransactionState e)
@@ -42,7 +43,7 @@
                    }
 
 -- | Run transaction against an event store.
-runTransactionT :: (Typeable a, Typeable e, Event e a, Default a, Aggregate a) => EventStore -> TransactionT e IO c -> IO c
+runTransactionT :: (Typeable e, Event e) => EventStore -> TransactionT e IO c -> IO c
 runTransactionT eventStore_ (TransactionT transaction) = do
   withTransaction eventStore_ $ do
     -- Run the computation.
@@ -63,7 +64,7 @@
   where s0 = TransactionState eventStore_ [ ]
 
 -- | Get an aggregate ref by GUID.
-getById :: forall a e . (Typeable a, Typeable e, Event e a, Default a, Aggregate a) => GUID a -> TransactionT e IO (AggregateRef a e)
+getById :: forall a e . (Typeable a, Typeable e, Event e, Default a, Aggregate a, Eventable a e) => GUID a -> TransactionT e IO (AggregateRef a e)
 getById guid = TransactionT $ do
   -- Check through list to see if we've given out a reference to the aggregate before.
   aggregateRefs <- fmap aggregateRefsToCommit get
@@ -83,7 +84,7 @@
 
 -- Get the latest snapshot from database, filling in a default
 -- if a) no snapshot exists, or b) snapshot state was not decodable.
-getLatestSnapshot :: forall a e . (Typeable a, Typeable e, Event e a, Default a, Aggregate a) => GUID a -> Transaction e IO (Int,a)
+getLatestSnapshot :: forall a e . (Typeable a, Typeable e, Event e, Default a, Aggregate a) => GUID a -> Transaction e IO (Int,a)
 getLatestSnapshot guid = do
   es <- fmap eventStore get
   r <- liftIO $ ES.getLatestSnapshot es guid
@@ -96,7 +97,7 @@
       return (0, def)
 
 -- Retrieve aggregate from event store.
-getByIdFromEventStore :: forall a e . (Typeable a, Typeable e, Event e a, Default a, Aggregate a) => GUID a -> Transaction e IO (AggregateRef a e)
+getByIdFromEventStore :: forall a e . (Typeable a, Typeable e, Event e, Default a, Aggregate a, Eventable a e) => GUID a -> Transaction e IO (AggregateRef a e)
 getByIdFromEventStore guid = do
   es <- fmap eventStore get
   -- Get latest snapshot (if any).
@@ -113,7 +114,7 @@
   return a'
 
 -- | Publish event for an aggregate root.
-publishEvent :: (MonadIO m, Event e a) => AggregateRef a e -> e -> TransactionT e m ()
+publishEvent :: (MonadIO m, Event e, Eventable a e) => AggregateRef a e -> e -> TransactionT e m ()
 publishEvent aggregateRef event = lift $ AR.publishEvent aggregateRef event
 
 -- | Retrieve a range of events, invoking a callback function for each event.
@@ -128,7 +129,7 @@
 -- and "logical time" 30 (not inclusive). "Logical time" starts
 -- at 1. It is NOT an error to provide bounds for which there
 -- are no events.
-retrieveEvents :: forall e a . (Event e a) => Int -> Int -> (e -> IO ()) -> TransactionT e IO ()
+retrieveEvents :: forall e . (Event e) => Int -> Int -> (e -> IO ()) -> TransactionT e IO ()
 retrieveEvents minVersion maxVersion h = TransactionT $ do
   es <- fmap eventStore get
   lift $ ES.readAllEvents es minVersion maxVersion $ \ed -> do
@@ -136,7 +137,7 @@
     liftIO $ h e
 
 -- | Get aggregate root.
-getAggregateRoot :: (Default a, Event e a, Typeable a, Typeable e, Aggregate a) => GUID a -> TransactionT e IO (AggregateRef a e, a)
+getAggregateRoot :: (Default a, Event e, Typeable a, Typeable e, Aggregate a, Eventable a e) => GUID a -> TransactionT e IO (AggregateRef a e, a)
 getAggregateRoot guid = do
   aggregateRef <- getById guid
   aggregate <- lift $ AR.readValue aggregateRef
