diff --git a/bytestringparser.cabal b/bytestringparser.cabal
--- a/bytestringparser.cabal
+++ b/bytestringparser.cabal
@@ -1,5 +1,5 @@
 name:            bytestringparser
-version:         0.2
+version:         0.2.1
 license:         BSD3
 license-file:    LICENSE
 category:        Text, Parsing
@@ -27,5 +27,6 @@
 
   extensions:      CPP
   exposed-modules: Text.ParserCombinators.ByteStringParser
+                   Text.ParserCombinators.ByteStringParser.FastSet
   hs-source-dirs:  src
   ghc-options:     -O2 -Wall -Werror
diff --git a/src/Text/ParserCombinators/ByteStringParser.hs b/src/Text/ParserCombinators/ByteStringParser.hs
--- a/src/Text/ParserCombinators/ByteStringParser.hs
+++ b/src/Text/ParserCombinators/ByteStringParser.hs
@@ -1,8 +1,8 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Text.ParserCombinators.ByteStringParser
--- Copyright   :  (c) Daan Leijen 1999-2001, Jeremy Shaw 2006, Bryan O'Sullivan 2007
--- License     :  BSD-style (see the file libraries/parsec/LICENSE)
+-- Copyright   :  Daan Leijen 1999-2001, Jeremy Shaw 2006, Bryan O'Sullivan 2007-2008
+-- License     :  BSD3
 -- 
 -- Maintainer  :  bos@serpentine.com
 -- Stability   :  experimental
@@ -75,7 +75,7 @@
 import qualified Data.ByteString.Lazy.Internal as LB
 import Data.Char (isDigit, isLetter, isSpace, toLower)
 import Data.Int (Int64)
-import qualified Data.Set as S
+import Text.ParserCombinators.ByteStringParser.FastSet (FastSet, member, set)
 import Prelude hiding (takeWhile)
 
 type ParseError = String
@@ -209,19 +209,20 @@
 notChar c = satisfy (/= c) <?> "not " ++ [c]
 {-# INLINE notChar #-}
 
-charClass :: String -> S.Set Char
-charClass s = S.fromList (go s)
+charClass :: String -> FastSet
+charClass = set . SB.pack . go
     where go (a:'-':b:xs) = [a..b] ++ go xs
           go (x:xs) = x : go xs
           go _ = ""
 
 inClass :: String -> Char -> Bool
-inClass s = (`S.member` set)
-    where set = charClass s
+inClass s = (`member` myset)
+    where myset = charClass s
+{-# INLINE inClass #-}
 
 notInClass :: String -> Char -> Bool
-notInClass s = (`S.notMember` set)
-    where set = charClass s
+notInClass s = not . inClass s
+{-# INLINE notInClass #-}
 
 sepBy :: Parser a -> Parser s -> Parser [a]
 sepBy p s = liftM2 (:) p ((s >> sepBy1 p s) <|> return []) <|> return []
diff --git a/src/Text/ParserCombinators/ByteStringParser/FastSet.hs b/src/Text/ParserCombinators/ByteStringParser/FastSet.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/ParserCombinators/ByteStringParser/FastSet.hs
@@ -0,0 +1,41 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Text.ParserCombinators.ByteStringParser.FastSet
+-- Copyright   :  Bryan O'Sullivan 2008
+-- License     :  BSD3
+-- 
+-- Maintainer  :  bos@serpentine.com
+-- Stability   :  experimental
+-- Portability :  unknown
+--
+-- Fast 8-bit character set membership.
+-- 
+-----------------------------------------------------------------------------
+module Text.ParserCombinators.ByteStringParser.FastSet
+    (
+      FastSet
+    , set
+    , member
+    ) where
+
+import Data.ByteString.Char8 as SB
+import Data.ByteString.Internal as SB
+import Data.ByteString.Unsafe as SB
+
+newtype FastSet = FastSet SB.ByteString
+    deriving (Eq, Ord, Show)
+
+set :: SB.ByteString -> FastSet
+set = FastSet . SB.sort
+
+member :: Char -> FastSet -> Bool
+member c (FastSet s) = search 0 (SB.length s - 1)
+    where w = SB.c2w c
+          search lo hi | hi < lo = False
+                       | otherwise =
+                           let mid = (lo + hi) `div` 2
+                               cur = SB.unsafeIndex s mid
+                           in case compare cur w of
+                                GT -> search lo (mid - 1)
+                                LT -> search (mid + 1) hi
+                                _ -> True
