diff --git a/Text/Trifecta/CharSet.hs b/Text/Trifecta/CharSet.hs
--- a/Text/Trifecta/CharSet.hs
+++ b/Text/Trifecta/CharSet.hs
@@ -1,3 +1,4 @@
+{-# OPTIONS_GHC -fspec-constr #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Text.Trifecta.CharSet
@@ -83,15 +84,16 @@
 import qualified Prelude as P
 import Text.Read
 
-data CharSet 
-  = Pos AsciiSet !IntSet 
-  | Neg AsciiSet !IntSet
+data CharSet = S !Bool AsciiSet !IntSet 
 
+charSet :: Bool -> IntSet -> CharSet
+charSet b s = S b (AsciiSet.fromList (fmap toEnum (takeWhile (<= 0x7f) (I.toAscList s)))) s
+
 pos :: IntSet -> CharSet
-pos s = Pos (AsciiSet.fromList (fmap toEnum (takeWhile (<= 0x7f) (I.toAscList s)))) s
+pos = charSet True
 
 neg :: IntSet -> CharSet
-neg s = Neg (AsciiSet.fromList (fmap toEnum (takeWhile (<= 0x7f) (I.toAscList s)))) s
+neg = charSet False
 
 (\\) :: CharSet -> CharSet -> CharSet
 (\\) = difference
@@ -101,23 +103,23 @@
 {-# INLINE build #-}
 
 map :: (Char -> Char) -> CharSet -> CharSet
-map f (Pos _ i) = pos (I.map (fromEnum . f . toEnum) i)
-map f (Neg _ i) = fromList $ P.map f $ P.filter (\x -> fromEnum x `I.notMember` i) [ul..uh] 
+map f (S True _ i) = pos (I.map (fromEnum . f . toEnum) i)
+map f (S False _ i) = fromList $ P.map f $ P.filter (\x -> fromEnum x `I.notMember` i) [ul..uh] 
 {-# INLINE map #-}
 
 isComplemented :: CharSet -> Bool
-isComplemented (Pos _ _) = False
-isComplemented (Neg _ _) = True
+isComplemented (S True _ _) = False
+isComplemented (S False _ _) = True
 {-# INLINE isComplemented #-}
 
 toList :: CharSet -> String
-toList (Pos _ i) = P.map toEnum (I.toList i)
-toList (Neg _ i) = P.filter (\x -> fromEnum x `I.notMember` i) [ul..uh]
+toList (S True _ i) = P.map toEnum (I.toList i)
+toList (S False _ i) = P.filter (\x -> fromEnum x `I.notMember` i) [ul..uh]
 {-# INLINE toList #-}
 
 toAscList :: CharSet -> String
-toAscList (Pos _ i) = P.map toEnum (I.toAscList i)
-toAscList (Neg _ i) = P.filter (\x -> fromEnum x `I.notMember` i) [ul..uh]
+toAscList (S True _ i) = P.map toEnum (I.toAscList i)
+toAscList (S False _ i) = P.filter (\x -> fromEnum x `I.notMember` i) [ul..uh]
 {-# INLINE toAscList #-}
     
 empty :: CharSet
@@ -132,19 +134,19 @@
 
 -- | /O(n)/ worst case
 null :: CharSet -> Bool
-null (Pos _ i) = I.null i
-null (Neg _ i) = I.size i == numChars
+null (S True _ i) = I.null i
+null (S False _ i) = I.size i == numChars
 {-# INLINE null #-}
 
 -- | /O(n)/
 size :: CharSet -> Int
-size (Pos _ i) = I.size i
-size (Neg _ i) = numChars - I.size i
+size (S True _ i) = I.size i
+size (S False _ i) = numChars - I.size i
 {-# INLINE size #-}
 
 insert :: Char -> CharSet -> CharSet
-insert c (Pos _ i) = pos (I.insert (fromEnum c) i)
-insert c (Neg _ i) = neg (I.delete (fromEnum c) i)
+insert c (S True _ i) = pos (I.insert (fromEnum c) i)
+insert c (S False _ i) = neg (I.delete (fromEnum c) i)
 {-# INLINE insert #-}
 
 range :: Char -> Char -> CharSet
@@ -153,41 +155,41 @@
   | otherwise = empty
 
 delete :: Char -> CharSet -> CharSet
-delete c (Pos _ i) = pos (I.delete (fromEnum c) i)
-delete c (Neg _ i) = neg (I.insert (fromEnum c) i)
+delete c (S True _ i) = pos (I.delete (fromEnum c) i)
+delete c (S False _ i) = neg (I.insert (fromEnum c) i)
 {-# INLINE delete #-}
 
 complement :: CharSet -> CharSet
-complement (Pos s i) = Neg s i
-complement (Neg s i) = Pos s i
+complement (S True s i) = S False s i
+complement (S False s i) = S True s i
 {-# INLINE complement #-}
 
 union :: CharSet -> CharSet -> CharSet
-union (Pos _ i) (Pos _ j) = pos (I.union i j)
-union (Pos _ i) (Neg _ j) = neg (I.difference j i)
-union (Neg _ i) (Pos _ j) = neg (I.difference i j)
-union (Neg _ i) (Neg _ j) = neg (I.intersection i j)
+union (S True _ i) (S True _ j) = pos (I.union i j)
+union (S True _ i) (S False _ j) = neg (I.difference j i)
+union (S False _ i) (S True _ j) = neg (I.difference i j)
+union (S False _ i) (S False _ j) = neg (I.intersection i j)
 {-# INLINE union #-}
 
 intersection :: CharSet -> CharSet -> CharSet
-intersection (Pos _ i) (Pos _ j) = pos (I.intersection i j)
-intersection (Pos _ i) (Neg _ j) = pos (I.difference i j)
-intersection (Neg _ i) (Pos _ j) = pos (I.difference j i)
-intersection (Neg _ i) (Neg _ j) = neg (I.union i j)
+intersection (S True _ i) (S True _ j) = pos (I.intersection i j)
+intersection (S True _ i) (S False _ j) = pos (I.difference i j)
+intersection (S False _ i) (S True _ j) = pos (I.difference j i)
+intersection (S False _ i) (S False _ j) = neg (I.union i j)
 {-# INLINE intersection #-}
 
 difference :: CharSet -> CharSet -> CharSet 
-difference (Pos _ i) (Pos _ j) = pos (I.difference i j)
-difference (Pos _ i) (Neg _ j) = pos (I.intersection i j)
-difference (Neg _ i) (Pos _ j) = neg (I.union i j)
-difference (Neg _ i) (Neg _ j) = pos (I.difference j i)
+difference (S True _ i) (S True _ j) = pos (I.difference i j)
+difference (S True _ i) (S False _ j) = pos (I.intersection i j)
+difference (S False _ i) (S True _ j) = neg (I.union i j)
+difference (S False _ i) (S False _ j) = pos (I.difference j i)
 {-# INLINE difference #-}
 
 member :: Char -> CharSet -> Bool
-member c (Pos b i)
+member c (S True b i)
   | c <= toEnum 0x7f = AsciiSet.member c b
   | otherwise        = I.member (fromEnum c) i
-member c (Neg b i) 
+member c (S False b i) 
   | c <= toEnum 0x7f = not (AsciiSet.member c b)
   | otherwise        = I.notMember (fromEnum c) i
 {-# INLINE member #-}
@@ -197,34 +199,34 @@
 {-# INLINE notMember #-}
 
 fold :: (Char -> b -> b) -> b -> CharSet -> b
-fold f z (Pos _ i) = I.fold (f . toEnum) z i
-fold f z (Neg _ i) = foldr f z $ P.filter (\x -> fromEnum x `I.notMember` i) [ul..uh]
+fold f z (S True _ i) = I.fold (f . toEnum) z i
+fold f z (S False _ i) = foldr f z $ P.filter (\x -> fromEnum x `I.notMember` i) [ul..uh]
 {-# INLINE fold #-}
 
 filter :: (Char -> Bool) -> CharSet -> CharSet 
-filter p (Pos _ i) = pos (I.filter (p . toEnum) i)
-filter p (Neg _ i) = neg $ foldr (I.insert) i $ P.filter (\x -> (x `I.notMember` i) && not (p (toEnum x))) [ol..oh]
+filter p (S True _ i) = pos (I.filter (p . toEnum) i)
+filter p (S False _ i) = neg $ foldr (I.insert) i $ P.filter (\x -> (x `I.notMember` i) && not (p (toEnum x))) [ol..oh]
 {-# INLINE filter #-}
 
 partition :: (Char -> Bool) -> CharSet -> (CharSet, CharSet)
-partition p (Pos _ i) = (pos l, pos r)
+partition p (S True _ i) = (pos l, pos r)
     where (l,r) = I.partition (p . toEnum) i
-partition p (Neg _ i) = (neg (foldr I.insert i l), neg (foldr I.insert i r))
+partition p (S False _ i) = (neg (foldr I.insert i l), neg (foldr I.insert i r))
     where (l,r) = L.partition (p . toEnum) $ P.filter (\x -> x `I.notMember` i) [ol..oh]
 {-# INLINE partition #-}
 
 overlaps :: CharSet -> CharSet -> Bool
-overlaps (Pos _ i) (Pos _ j) = not (I.null (I.intersection i j))
-overlaps (Pos _ i) (Neg _ j) = not (I.isSubsetOf j i)
-overlaps (Neg _ i) (Pos _ j) = not (I.isSubsetOf i j)
-overlaps (Neg _ i) (Neg _ j) = any (\x -> I.notMember x i && I.notMember x j) [ol..oh] -- not likely
+overlaps (S True _ i) (S True _ j) = not (I.null (I.intersection i j))
+overlaps (S True _ i) (S False _ j) = not (I.isSubsetOf j i)
+overlaps (S False _ i) (S True _ j) = not (I.isSubsetOf i j)
+overlaps (S False _ i) (S False _ j) = any (\x -> I.notMember x i && I.notMember x j) [ol..oh] -- not likely
 {-# INLINE overlaps #-}
 
 isSubsetOf :: CharSet -> CharSet -> Bool
-isSubsetOf (Pos _ i) (Pos _ j) = I.isSubsetOf i j
-isSubsetOf (Pos _ i) (Neg _ j) = I.null (I.intersection i j)
-isSubsetOf (Neg _ i) (Pos _ j) = all (\x -> I.member x i && I.member x j) [ol..oh] -- not bloody likely
-isSubsetOf (Neg _ i) (Neg _ j) = I.isSubsetOf j i
+isSubsetOf (S True _ i) (S True _ j) = I.isSubsetOf i j
+isSubsetOf (S True _ i) (S False _ j) = I.null (I.intersection i j)
+isSubsetOf (S False _ i) (S True _ j) = all (\x -> I.member x i && I.member x j) [ol..oh] -- not bloody likely
+isSubsetOf (S False _ i) (S False _ j) = I.isSubsetOf j i
 {-# INLINE isSubsetOf #-}
 
 fromList :: String -> CharSet 
@@ -295,10 +297,9 @@
 charSetDataType  = mkDataType "Text.Trifecta.CharSet.CharSet" [fromListConstr, complementConstr]
 {-# NOINLINE charSetDataType #-}
 
--- returns an intset and if the intset should be complemented to obtain the contents of the CharSet
+-- returns an intset and if the charSet is positive
 fromCharSet :: CharSet -> (Bool, IntSet)
-fromCharSet (Pos _ i) = (False, i)
-fromCharSet (Neg _ i) = (True, i) 
+fromCharSet (S b _ i) = (b, i)
 {-# INLINE fromCharSet #-}
 
 toCharSet :: IntSet -> CharSet
diff --git a/Text/Trifecta/Parser/Prim.hs b/Text/Trifecta/Parser/Prim.hs
--- a/Text/Trifecta/Parser/Prim.hs
+++ b/Text/Trifecta/Parser/Prim.hs
@@ -126,9 +126,9 @@
   {-# INLINE listen #-}
   pass (Parser m) = Parser $ \eo ee co ce l -> 
     m (\(a,p) e' l' -> eo a e' (l <> p l'))
-      (\      e' l' -> ee   e' (l <> l'))
+      (\      e' l' -> ee   e' (l <>   l'))
       (\(a,p) e' l' -> co a e' (l <> p l'))
-      (\      e' l' -> ce   e' (l <> l'))
+      (\      e' l' -> ce   e' (l <>   l'))
       mempty
   {-# INLINE pass #-}
 
diff --git a/trifecta.cabal b/trifecta.cabal
--- a/trifecta.cabal
+++ b/trifecta.cabal
@@ -1,6 +1,6 @@
 name:          trifecta
 category:      Text, Parsing, Diagnostics, Pretty Printer, Logging
-version:       0.24
+version:       0.25
 license:       BSD3
 cabal-version: >= 1.6
 license-file:  LICENSE
@@ -82,7 +82,7 @@
     mtl                  >= 2.0.1   && < 2.1,
     semigroups           >= 0.7.1   && < 0.8, 
     fingertree           >= 0.0.1   && < 0.1,
-    reducers             >= 0.1.2   && < 0.2,
+    reducers             >= 0.1.4   && < 0.2,
     profunctors          >= 0.1.1   && < 0.2,
     utf8-string          >= 0.3.6   && < 0.4,
     semigroupoids        >= 1.2.4   && < 1.3,
@@ -90,6 +90,6 @@
     transformers         >= 0.2.2   && < 0.3,
     comonad              >= 1.1.1   && < 1.2,
     terminfo             >= 0.3.2   && < 0.4,
-    keys                 >= 2.0.1   && < 2.1,
+    keys                 >= 2.1     && < 2.2,
     wl-pprint-extras     >= 1.4     && < 1.5,
     wl-pprint-terminfo   >= 0.4     && < 0.5
