diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 Data-Serializer
 ===============
 
-[![Hackage](https://img.shields.io/hackage/v/data-serializer.svg)](http://hackage.haskell.org/package/data-serializer)
+[![Travis](https://img.shields.io/travis/mvv/data-serializer/master.svg)](https://travis-ci.org/mvv/data-serializer) [![Hackage](https://img.shields.io/hackage/v/data-serializer.svg)](http://hackage.haskell.org/package/data-serializer)
 
 This package provides a common API for serialization libraries like
 [binary](http://hackage.haskell.org/package/binary) and
diff --git a/data-serializer.cabal b/data-serializer.cabal
--- a/data-serializer.cabal
+++ b/data-serializer.cabal
@@ -1,5 +1,5 @@
 Name: data-serializer
-Version: 0.2
+Version: 0.3
 Category: Data
 Stability: experimental
 Synopsis: Common API for serialization libraries
@@ -20,6 +20,8 @@
 Extra-Source-Files:
   README.md
 
+Tested-With: GHC==7.10.3, GHC==8.0.1
+
 Cabal-Version: >= 1.10.0
 Build-Type: Simple
 
@@ -29,10 +31,11 @@
 
 Library
   Default-Language: Haskell2010
-  Build-Depends: base >= 4.7 && < 5
+  Build-Depends: base >= 4.8 && < 5
+               , semigroups >= 0.18.2
                , bytestring >= 0.10.4
                , binary >= 0.7.2
-               , cereal >= 0.5.3
+               , cereal >= 0.4.1
                , data-endian >= 0.1.1
                , parsers >= 0.12.3
   Hs-Source-Dirs: src
diff --git a/src/Data/Serializer.hs b/src/Data/Serializer.hs
--- a/src/Data/Serializer.hs
+++ b/src/Data/Serializer.hs
@@ -12,6 +12,8 @@
   (
   -- * Serialization monoid
     Serializer(..)
+  , BinarySerializer(..)
+  , CerealSerializer(..)
   -- ** Binary words serialization
   , word16H
   , word32H
@@ -56,7 +58,8 @@
 import Data.Typeable (Typeable)
 import Data.Data (Data)
 import Data.Proxy (Proxy(..))
-import Data.Monoid (Monoid, (<>))
+import Data.Semigroup (Semigroup, (<>))
+import Data.Monoid (Monoid)
 import Data.Endian (Endian(..), swapEndian)
 import Data.Word
 import Data.Int
@@ -69,7 +72,7 @@
 import qualified Data.Serialize.Put as S
 
 -- | Serialization monoid.
-class Monoid s ⇒ Serializer s where
+class (Semigroup s, Monoid s) ⇒ Serializer s where
   {-# MINIMAL word8 #-}
   -- | Default byte order of the serializer.
   endian ∷ Proxy s → Endian
@@ -173,6 +176,7 @@
   builder = id
   {-# INLINE builder #-}
 
+#if MIN_VERSION_base(4,9,0) && MIN_VERSION_binary(0,8,3)
 instance Serializer B.Put where
   word8 = B.putWord8
   {-# INLINE word8 #-}
@@ -196,31 +200,109 @@
   {-# INLINE lazyByteString #-}
   builder = B.putBuilder
   {-# INLINE builder #-}
+#endif
 
-instance Serializer S.Put where
-  word8 = S.putWord8
+-- | A wrapper around the 'B.Put' monoid (to avoid orphan instances).
+newtype BinarySerializer = BinarySerializer { binarySerializer ∷ B.Put }
+                           deriving ( Typeable, Generic
+#if MIN_VERSION_binary(0,8,3)
+# if MIN_VERSION_base(4,9,0)
+                                    , Semigroup
+# endif
+                                    , Monoid
+#endif
+                                    )
+
+#if !MIN_VERSION_base(4,9,0) || !MIN_VERSION_binary(0,8,3)
+instance Semigroup BinarySerializer where
+  s₁ <> s₂ = BinarySerializer $ binarySerializer s₁ >> binarySerializer s₂
+  {-# INLINE (<>) #-}
+#endif
+
+#if !MIN_VERSION_binary(0,8,3)
+instance Monoid BinarySerializer where
+  mempty = BinarySerializer $ return ()
+  {-# INLINE mempty #-}
+  mappend = (<>)
+  {-# INLINE mappend #-}
+#endif
+
+instance Serializer BinarySerializer where
+  word8 = BinarySerializer . B.putWord8
   {-# INLINE word8 #-}
-  word16L = S.putWord16le
+  word16L = BinarySerializer . B.putWord16le
   {-# INLINE word16L #-}
-  word16B = S.putWord16be
+  word16B = BinarySerializer . B.putWord16be
   {-# INLINE word16B #-}
-  word32L = S.putWord32le
+  word32L = BinarySerializer . B.putWord32le
   {-# INLINE word32L #-}
-  word32B = S.putWord32be
+  word32B = BinarySerializer . B.putWord32be
   {-# INLINE word32B #-}
-  word64L = S.putWord64le
+  word64L = BinarySerializer . B.putWord64le
   {-# INLINE word64L #-}
-  word64B = S.putWord64be
+  word64B = BinarySerializer . B.putWord64be
   {-# INLINE word64B #-}
-  byteString = S.putByteString
+  byteString = BinarySerializer . B.putByteString
   {-# INLINE byteString #-}
-  shortByteString = S.putShortByteString
+#if MIN_VERSION_binary(0,8,1)
+  shortByteString = BinarySerializer . B.putShortByteString
   {-# INLINE shortByteString #-}
-  lazyByteString = S.putLazyByteString
+#endif
+  lazyByteString = BinarySerializer . B.putLazyByteString
   {-# INLINE lazyByteString #-}
-  builder = S.putBuilder
+#if MIN_VERSION_binary(0,8,3)
+  builder = BinarySerializer . B.putBuilder
   {-# INLINE builder #-}
+#endif
 
+-- | A wrapper around the 'S.Put' monoid (to avoid orphan instances).
+newtype CerealSerializer = CerealSerializer { cerealSerializer ∷ S.Put }
+                           deriving ( Typeable, Generic
+#if MIN_VERSION_cereal(0,5,3)
+                                    , Monoid
+#endif
+                                    )
+
+instance Semigroup CerealSerializer where
+  s₁ <> s₂ = CerealSerializer $ cerealSerializer s₁ >> cerealSerializer s₂
+  {-# INLINE (<>) #-}
+
+#if !MIN_VERSION_cereal(0,5,3)
+instance Monoid CerealSerializer where
+  mempty = CerealSerializer $ return ()
+  {-# INLINE mempty #-}
+  mappend = (<>)
+  {-# INLINE mappend #-}
+#endif
+
+instance Serializer CerealSerializer where
+  word8 = CerealSerializer . S.putWord8
+  {-# INLINE word8 #-}
+  word16L = CerealSerializer . S.putWord16le
+  {-# INLINE word16L #-}
+  word16B = CerealSerializer . S.putWord16be
+  {-# INLINE word16B #-}
+  word32L = CerealSerializer . S.putWord32le
+  {-# INLINE word32L #-}
+  word32B = CerealSerializer . S.putWord32be
+  {-# INLINE word32B #-}
+  word64L = CerealSerializer . S.putWord64le
+  {-# INLINE word64L #-}
+  word64B = CerealSerializer . S.putWord64be
+  {-# INLINE word64B #-}
+  byteString = CerealSerializer . S.putByteString
+  {-# INLINE byteString #-}
+#if MIN_VERSION_cereal(0,5,0)
+  shortByteString = CerealSerializer . S.putShortByteString
+  {-# INLINE shortByteString #-}
+#endif
+  lazyByteString = CerealSerializer . S.putLazyByteString
+  {-# INLINE lazyByteString #-}
+#if MIN_VERSION_cereal(0,5,0)
+  builder = CerealSerializer . S.putBuilder
+  {-# INLINE builder #-}
+#endif
+
 -- | Serialize an usigned 16-bit integer in host byte order.
 word16H ∷ Serializer s ⇒ Word16 → s
 #ifdef WORDS_BIGENDIAN
@@ -400,7 +482,8 @@
 
 -- | Serializer wrapper with little endian default byte order.
 newtype LittleEndianSerializer s = LittleEndianSerializer { serializeL ∷ s }
-                                   deriving (Typeable, Data, Generic, Monoid)
+                                   deriving (Typeable, Data, Generic,
+                                             Semigroup, Monoid)
 
 instance Serializer s ⇒ Serializer (LittleEndianSerializer s) where
   endian _ = LittleEndian
@@ -436,7 +519,8 @@
 
 -- | Serializer wrapper with big endian default byte order.
 newtype BigEndianSerializer s = BigEndianSerializer { serializeB ∷ s }
-                                deriving (Typeable, Data, Generic, Monoid)
+                                deriving (Typeable, Data, Generic,
+                                          Semigroup, Monoid)
 
 instance Serializer s ⇒ Serializer (BigEndianSerializer s) where
   endian _ = BigEndian
diff --git a/tests/Tests.hs b/tests/Tests.hs
--- a/tests/Tests.hs
+++ b/tests/Tests.hs
@@ -23,8 +23,8 @@
 import Control.Applicative ((<|>))
 
 byteStringBuilder = LBS.unpack . BB.toLazyByteString
-binaryBuilder = LBS.unpack . B.runPut
-cerealBuilder = LBS.unpack . C.runPutLazy
+binaryBuilder = LBS.unpack . B.runPut . S.binarySerializer
+cerealBuilder = LBS.unpack . C.runPutLazy . S.cerealSerializer
 
 serializerTests ∷ Serializer s ⇒ String → (s → [Word8]) → TestTree
 serializerTests name build =
