diff --git a/Data/Char8.hs b/Data/Char8.hs
new file mode 100644
--- /dev/null
+++ b/Data/Char8.hs
@@ -0,0 +1,167 @@
+{-# LANGUAGE MagicHash #-}
+
+-- | Char8 library to be used with Data.ByteString.Char8
+
+module Data.Char8 (
+  -- * Character classification
+    isControl, isSpace, isLower, isUpper
+  , isAlpha, isAlphaNum, isPrint, isDigit, isOctDigit, isHexDigit
+  , isLetter, isMark, isNumber, isPunctuation, isSymbol, isSeparator
+  -- * Subranges
+  , isAscii, isLatin1, isAsciiUpper, isAsciiLower
+  -- * Case conversion
+  , toUpper, toLower, toTitle
+  ) where
+
+import GHC.Base
+----------------------------------------------------------------
+
+isControl :: Char -> Bool
+isControl c = _nul <= c && c <= '\x1f'
+           || _del <= c && c <= '\x9f'
+
+isSpace :: Char -> Bool
+isSpace c = c == _space
+         || c == _tab
+         || c == _lf
+         || c == _cr
+         || c == _np
+         || c == _vt
+         || c == _nbsp
+
+isLower :: Char -> Bool
+isLower c = isLower' c
+         || c == _ordfeminine
+         || c == _mu
+         || c == _ordmasculine
+
+isLower' :: Char -> Bool
+isLower' c = isAsciiLower c
+          || _germandbls <= c && c <= _odieresis
+          || _oslash     <= c && c <= _ydieresis
+
+isUpper :: Char -> Bool
+isUpper c = isAsciiUpper c
+         || _Agrave <= c && c <= _Odieresis
+         || _Oslash <= c && c <= _Thorn
+
+isAlpha :: Char -> Bool
+isAlpha c = isLower c || isUpper c
+
+isAlphaNum :: Char -> Bool
+isAlphaNum c = isAlpha c || isNumber c
+
+isPrint :: Char -> Bool
+isPrint c
+  | c == _softhyphen = False
+isPrint c = _space <= c && c <= '~'
+         || _nbsp  <= c && c <= _ydieresis
+
+isDigit :: Char -> Bool
+isDigit c = '0' <= c && c <= '9'
+
+isOctDigit :: Char -> Bool
+isOctDigit c = '0' <= c && c <= '7'
+
+isHexDigit :: Char -> Bool
+isHexDigit c = isDigit c
+            || 'A' <= c && c <= 'F'
+            || 'a' <= c && c <= 'f'
+
+isLetter :: Char -> Bool
+isLetter c = isLower c || isUpper c
+
+isMark :: Char -> Bool
+isMark _ = False
+
+isNumber :: Char -> Bool
+isNumber c = isDigit c
+          || c == _s1
+          || c == _s2
+          || c == _s3
+          || c == _1'4
+          || c == _1'2
+          || c == _3'4
+
+isPunctuation :: Char -> Bool
+isPunctuation c = c `elem` ['\x21','\x22','\x23','\x25','\x26','\x27','\x28','\x29','\x2a','\x2c','\x2d','\x2e','\x2f','\x3a','\x3b','\x3f','\x40','\x5b','\x5c','\x5d','\x5f','\x7b','\x7d','\xa1','\xab','\xb7','\xbb','\xbf']
+
+isSymbol :: Char -> Bool
+isSymbol c = c `elem` ['\x24','\x2b','\x3c','\x3d','\x3e','\x5e','\x60','\x7c','\x7e','\xa2','\xa3','\xa4','\xa5','\xa6','\xa7','\xa8','\xa9','\xac','\xae','\xaf','\xb0','\xb1','\xb4','\xb6','\xb8','\xd7','\xf7']
+
+isSeparator :: Char -> Bool
+isSeparator c = c == _space
+             || c == _nbsp
+
+----------------------------------------------------------------
+
+isAscii :: Char -> Bool
+isAscii c = _nul <= c && c <= _del
+
+isLatin1 :: Char -> Bool
+isLatin1 _ = True
+
+isAsciiUpper :: Char -> Bool
+isAsciiUpper c = 'A' <= c && c <= 'Z'
+
+isAsciiLower :: Char -> Bool
+isAsciiLower c = 'a' <= c && c <= 'z'
+
+----------------------------------------------------------------
+
+toUpper :: Char -> Char
+toUpper c@(C# c#)
+  | c == _germandbls = c
+  | isLower' c       = C# (chr# (ord# c# -# 32#))
+  | otherwise        = c
+
+toLower :: Char -> Char
+toLower c@(C# c#)
+  | isUpper c = C# (chr# (ord# c# +# 32#))
+  | otherwise = c
+
+toTitle :: Char -> Char
+toTitle = toUpper
+
+----------------------------------------------------------------
+
+_nul, _tab, _lf, _vt, _np, _cr :: Char
+_nul = '\x00'
+_tab = '\x09'
+_lf  = '\x0a'
+_vt  = '\x0b'
+_np  = '\x0c'
+_cr  = '\x0d'
+
+_space, _del, _nbsp :: Char
+_space = '\x20'
+_del   = '\x7f'
+_nbsp  = '\xa0'
+
+_ordfeminine, _softhyphen, _mu, _ordmasculine :: Char
+_ordfeminine  = '\xaa'
+_softhyphen   = '\xad'
+_mu           = '\xb5'
+_ordmasculine = '\xba'
+
+_s2, _s3, _s1, _1'4, _1'2, _3'4  :: Char
+_s2 = '\xb2'
+_s3 = '\xb3'
+_s1 = '\xb9'
+_1'4 = '\xbc'
+_1'2 = '\xbd'
+_3'4 = '\xbe'
+
+_Agrave, _Odieresis, _Oslash, _Thorn :: Char
+_Agrave    = '\xc0'
+_Odieresis = '\xd6'
+_Oslash    = '\xd8'
+_Thorn     = '\xde'
+
+_germandbls, _agrave, _odieresis, _oslash, _thorn, _ydieresis :: Char
+_germandbls = '\xdf'
+_agrave     = '\xe0'
+_odieresis  = '\xf6'
+_oslash     = '\xf8'
+_thorn      = '\xfe'
+_ydieresis  = '\xff'
diff --git a/word8.cabal b/word8.cabal
--- a/word8.cabal
+++ b/word8.cabal
@@ -1,5 +1,5 @@
 Name:                   word8
-Version:                0.0.0
+Version:                0.0.1
 Author:                 Kazu Yamamoto <kazu@iij.ad.jp>
 Maintainer:             Kazu Yamamoto <kazu@iij.ad.jp>
 License:                BSD3
@@ -12,7 +12,8 @@
 
 Library
   GHC-Options:          -Wall
-  Exposed-Modules:      Data.Word8
+  Exposed-Modules:      Data.Char8
+                        Data.Word8
   Build-Depends:        base >= 4 && < 5
 
 Source-Repository head
