diff --git a/midi.cabal b/midi.cabal
--- a/midi.cabal
+++ b/midi.cabal
@@ -1,13 +1,13 @@
 Name:             midi
-Version:          0.2.2.1
+Version:          0.2.2.2
 License:          GPL
 License-File:     LICENSE
 Author:           Henning Thielemann <haskell@henning-thielemann.de>
 Maintainer:       Henning Thielemann <haskell@henning-thielemann.de>
 Homepage:         http://www.haskell.org/haskellwiki/MIDI
 Category:         Sound, Music
-Tested-With:      GHC==6.4.1, GHC==6.8.2, GHC==6.10.4, GHC==6.12.3
 Tested-With:      GHC==7.0.4, GHC==7.2.2, GHC==7.4.2, GHC==7.6.3, GHC==7.8.4, GHC==7.10.1
+Tested-With:      GHC==8.4.1
 Cabal-Version:    >=1.14
 Build-Type:       Simple
 Synopsis:         Handling of MIDI messages and files
@@ -30,29 +30,22 @@
 Source-Repository this
   type:     darcs
   location: http://hub.darcs.net/thielema/midi/
-  tag:      0.2.2.1
-
-Flag splitBase
-  description: Choose the new smaller, split-up base package.
+  tag:      0.2.2.2
 
 Library
   Build-Depends:
-    event-list >=0.0.9 && < 0.2,
+    event-list >=0.0.9 && <0.2,
     non-negative >=0.0.1 && <0.2,
+    semigroups >=0.1 && <1.0,
     utility-ht >=0.0.10 && <0.1,
     explicit-exception >=0.1 && <0.2,
     bytestring >=0.9.0.1 && <0.11,
     binary >=0.4.2 && <0.9,
     transformers >=0.2 && <0.6,
-    monoid-transformer >=0.0.1 && <0.1,
-    QuickCheck >=2.1 && <3
-  If flag(splitBase)
-    Build-Depends:
-      random >=1 && <2,
-      base >=3 && <5
-  Else
-    Build-Depends:
-      base >=1.0 && <3
+    monoid-transformer >=0.0.4 && <0.1,
+    QuickCheck >=2.1 && <3,
+    random >=1 && <2,
+    base >=3 && <5
 
   Default-Language: Haskell2010
   GHC-Options:      -Wall
@@ -129,3 +122,7 @@
     Example
     Parser
     Common
+    Sound.MIDI.Parser.Class
+    Sound.MIDI.Parser.Exception
+    Sound.MIDI.Parser.Stream
+    Sound.MIDI.Parser.Warning
diff --git a/src/Sound/MIDI/File/Save.hs b/src/Sound/MIDI/File/Save.hs
--- a/src/Sound/MIDI/File/Save.hs
+++ b/src/Sound/MIDI/File/Save.hs
@@ -19,10 +19,10 @@
 
 import qualified Sound.MIDI.Writer.Status as StatusWriter
 import qualified Sound.MIDI.Writer.Basic  as Writer
-import qualified Sound.MIDI.Monoid as M
 import Sound.MIDI.Monoid ((+#+))
 
 import qualified Data.Monoid.Transformer as Trans
+import Data.Foldable (foldMap, )
 
 import Sound.MIDI.IO (ByteList, writeBinaryFile, )
 
@@ -88,7 +88,7 @@
       Writer.putInt 2 (fromEnum mft) +#+ -- format (type 0, 1 or 2)
       Writer.putInt 2 (length trks)  +#+ -- number of tracks to come
       putDivision divisn)                 -- time unit
-   +#+ M.concatMap putTrack trks
+   +#+ foldMap putTrack trks
 
 putDivision :: Writer.C writer => Division -> writer
 putDivision (Ticks nticks) =
diff --git a/src/Sound/MIDI/Monoid.hs b/src/Sound/MIDI/Monoid.hs
--- a/src/Sound/MIDI/Monoid.hs
+++ b/src/Sound/MIDI/Monoid.hs
@@ -1,7 +1,9 @@
 module Sound.MIDI.Monoid where
 
-import Data.Monoid (Monoid, mappend, mconcat, )
-import Prelude hiding (concatMap, )
+import Data.Foldable (foldMap, )
+import Data.Monoid (Monoid, mappend, )
+import Data.Semigroup (Semigroup, sconcat, )
+import Data.List.NonEmpty (NonEmpty, )
 
 
 
@@ -19,9 +21,9 @@
 genConcat :: (Monoid m) =>
    (m -> a) -> (a -> m) -> [a] -> a
 genConcat cons decons =
-   cons . concatMap decons
+   cons . foldMap decons
 
--- foldMap
-concatMap :: (Monoid m) =>
-   (a -> m) -> [a] -> m
-concatMap f = mconcat . map f
+nonEmptyConcat :: (Semigroup m) =>
+   (m -> a) -> (a -> m) -> NonEmpty a -> a
+nonEmptyConcat cons decons =
+   cons . sconcat . fmap decons
diff --git a/src/Sound/MIDI/Writer/Basic.hs b/src/Sound/MIDI/Writer/Basic.hs
--- a/src/Sound/MIDI/Writer/Basic.hs
+++ b/src/Sound/MIDI/Writer/Basic.hs
@@ -4,13 +4,14 @@
 
 import qualified Sound.MIDI.Bit as Bit
 import qualified Sound.MIDI.IO as MIO
-import qualified Sound.MIDI.Monoid as M
 import qualified Data.Monoid as Monoid
 
 import Data.Bits ((.|.))
 import Sound.MIDI.IO (listByteFromChar, )
+import Sound.MIDI.Monoid ((+#+), genAppend, genConcat, nonEmptyConcat, )
+import Data.Foldable (foldMap, )
 import Data.Monoid (Monoid, mempty, mappend, mconcat, )
-import Sound.MIDI.Monoid ((+#+), genAppend, genConcat, )
+import Data.Semigroup (Semigroup(sconcat, (<>)), )
 
 import Control.Monad.Trans.Reader (ReaderT, runReaderT, ask, )
 import Control.Monad.Trans.Class (lift, )
@@ -44,6 +45,10 @@
 -- differences list
 newtype ByteList = ByteList {unByteList :: Monoid.Endo MIO.ByteList}
 
+instance Semigroup ByteList where
+   (<>) = genAppend ByteList unByteList
+   sconcat = nonEmptyConcat ByteList unByteList
+
 instance Monoid ByteList where
    mempty = ByteList mempty
    mappend = genAppend ByteList unByteList
@@ -70,6 +75,10 @@
 
 newtype ByteString = ByteString {unByteString :: Builder}
 
+instance Semigroup ByteString where
+   (<>) = genAppend ByteString unByteString
+   sconcat = nonEmptyConcat ByteString unByteString
+
 instance Monoid ByteString where
    mempty = ByteString $ mempty
    mappend = genAppend ByteString unByteString
@@ -95,10 +104,13 @@
 
 newtype SeekableFile = SeekableFile {unSeekableFile :: ReaderT Handle IO ()}
 
+instance Semigroup SeekableFile where
+   x <> y = SeekableFile $ unSeekableFile x >> unSeekableFile y
+
 instance Monoid SeekableFile where
    mempty = SeekableFile $ return ()
-   mappend x y = SeekableFile $ unSeekableFile x >> unSeekableFile y
-   mconcat xs  = SeekableFile $ mapM_ unSeekableFile xs
+   mappend = (<>)
+   mconcat = SeekableFile . mapM_ unSeekableFile
 
 instance C SeekableFile where
    putByte c =
@@ -146,7 +158,7 @@
 putIntAsByte x = putByte $ fromIntegral x
 
 putByteList :: C writer => MIO.ByteList -> writer
-putByteList = M.concatMap putByte
+putByteList = foldMap putByte
 
 putLenByteList :: C writer => MIO.ByteList -> writer
 putLenByteList bytes =
diff --git a/src/Sound/MIDI/Writer/Status.hs b/src/Sound/MIDI/Writer/Status.hs
--- a/src/Sound/MIDI/Writer/Status.hs
+++ b/src/Sound/MIDI/Writer/Status.hs
@@ -11,7 +11,8 @@
 
 import qualified Data.Monoid.HT as MonoidHT
 import Data.Monoid (Monoid, mempty, mappend, mconcat, )
-import Sound.MIDI.Monoid (genAppend, genConcat, )
+import Data.Semigroup (Semigroup, sconcat, (<>), )
+import Sound.MIDI.Monoid (genAppend, genConcat, nonEmptyConcat, )
 
 
 data Uncompressed = Uncompressed
@@ -25,6 +26,10 @@
 -}
 newtype T compress writer = Cons {decons :: State.T compress writer}
 
+
+instance Semigroup writer => Semigroup (T compress writer) where
+   Cons x <> Cons y = Cons $ x<>y
+   sconcat = nonEmptyConcat Cons decons
 
 instance Monoid writer => Monoid (T compress writer) where
    mempty = Cons $ mempty
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -116,7 +116,7 @@
 compressible :: MidiFile.T -> Bool
 compressible =
    any (or . ListHT.mapAdjacent equalStatus . EventList.getBodies) .
-   MidiFile.getTracks
+   MidiFile.getTracks . MidiFile.implicitNoteOff
 
 compressionStrictlyShortens :: MidiFile.T -> QC.Property
 compressionStrictlyShortens midi =
