diff --git a/ascii-superset.cabal b/ascii-superset.cabal
--- a/ascii-superset.cabal
+++ b/ascii-superset.cabal
@@ -1,7 +1,7 @@
 cabal-version: 3.0
 
 name: ascii-superset
-version: 1.0.2.0
+version: 1.1.0.0
 synopsis: Representing ASCII with refined supersets
 category: Data, Text
 
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,22 @@
+### 1.1.0.0 (2023-01-03)
+
+Add classes `ToChar` (`isAsciiChar`, `toCharUnsafe`) and `FromChar`
+(`fromChar`), of which `CharSuperset` is now a subclass with no methods of its
+own.
+
+Add classes `ToString` (`isAsciiString`, `toCharListUnsafe`, `toCharListSub`)
+and `FromString` (`fromCharList`), of which `StringSuperset` is now a subclass
+which still has some methods (`substituteString` and `mapCharsUnsafe`).
+
+Add class `ToCaselessChar` (`isAsciiCaselessChar`, `toCaselessCharUnsafe`),
+which is a superclass of `ToChar`. Also added related functions
+`toCaselessCharMaybe`, `toCaselessCharOrFail`, and `toCaselessCharSub`.
+
+Add class `ToCaselessString` (`isAsciiCaselessString`,
+`toCaselessCharListUnsafe`, `toCaselessCharListSub`) which is a superclass of
+`ToString`. Also added related functions `toCaselessCharListMaybe` and
+`toCaselessCharListOrFail`.
+
 ### 1.0.2.0 (2023-01-02)
 
 Add module `ASCII.CaseRefinement`
diff --git a/library/ASCII/Isomorphism.hs b/library/ASCII/Isomorphism.hs
--- a/library/ASCII/Isomorphism.hs
+++ b/library/ASCII/Isomorphism.hs
@@ -1,7 +1,7 @@
 module ASCII.Isomorphism (CharIso (..), asChar, StringIso (..)) where
 
 import ASCII.Char (Char)
-import ASCII.Superset (CharSuperset (..), StringSuperset (..))
+import ASCII.Superset (CharSuperset, StringSuperset, fromChar)
 import Data.Function (id, (.))
 import Data.List (map)
 
diff --git a/library/ASCII/Refinement.hs b/library/ASCII/Refinement.hs
--- a/library/ASCII/Refinement.hs
+++ b/library/ASCII/Refinement.hs
@@ -10,8 +10,6 @@
 import qualified ASCII.Isomorphism as I
 import qualified ASCII.Superset as S
 
-import ASCII.Superset (CharSuperset, StringSuperset)
-import Data.Bool (Bool (..))
 import Data.Data (Data)
 import Data.Eq (Eq)
 import Data.Function (id, ($), (.))
@@ -23,8 +21,10 @@
 import Data.Semigroup (Semigroup)
 import GHC.Generics (Generic)
 import Prelude (succ)
-import Text.Show (Show, showList, showParen, showString, showsPrec)
 
+import qualified Data.Bool as Bool
+import qualified Text.Show as Show
+
 {-| This type constructor indicates that a value from some ASCII superset is
 valid ASCII. The type parameter is the ASCII superset, which should be a type
 with an instance of either 'CharSuperset' or 'StringSuperset'.
@@ -48,29 +48,46 @@
 
 deriving stock instance Generic (ASCII superset)
 
-instance Show superset => Show (ASCII superset) where
-    showsPrec d x = showParen (d > app_prec) $
-        showString "asciiUnsafe " . showsPrec (succ app_prec) (lift x)
+instance Show.Show superset => Show.Show (ASCII superset) where
+    showsPrec d x = Show.showParen (d > app_prec) $
+        Show.showString "asciiUnsafe " . Show.showsPrec (succ app_prec) (lift x)
       where app_prec = 10
 
-    showList x = showString "asciiUnsafe " . showList (map lift x)
+    showList x = Show.showString "asciiUnsafe " . Show.showList (map lift x)
 
-instance CharSuperset char => CharSuperset (ASCII char) where
-    isAsciiChar _ = True
-    fromChar = asciiUnsafe . S.fromChar
+instance S.ToCaselessChar char => S.ToCaselessChar (ASCII char) where
+    isAsciiCaselessChar _ = Bool.True
+    toCaselessCharUnsafe = S.toCaselessCharUnsafe . lift
+
+instance S.CharSuperset char => S.ToChar (ASCII char) where
+    isAsciiChar _ = Bool.True
     toCharUnsafe = S.toCharUnsafe . lift
 
-instance CharSuperset char => I.CharIso (ASCII char) where
+instance S.CharSuperset char => S.FromChar (ASCII char) where
+    fromChar = asciiUnsafe . S.fromChar
+
+instance S.CharSuperset char => S.CharSuperset (ASCII char)
+
+instance S.CharSuperset char => I.CharIso (ASCII char) where
     toChar = S.toCharUnsafe
 
-instance StringSuperset string => StringSuperset (ASCII string) where
-    isAsciiString _ = True
-    fromCharList = asciiUnsafe . S.fromCharList
+instance S.ToCaselessString string => S.ToCaselessString (ASCII string) where
+    isAsciiCaselessString _ = Bool.True
+    toCaselessCharListUnsafe = S.toCaselessCharListUnsafe . lift
+    toCaselessCharListSub = S.toCaselessCharListSub . lift
+
+instance S.ToString string => S.ToString (ASCII string) where
+    isAsciiString _ = Bool.True
     toCharListUnsafe = S.toCharListUnsafe . lift
     toCharListSub = S.toCharListUnsafe . lift
+
+instance S.FromString string => S.FromString (ASCII string) where
+    fromCharList = asciiUnsafe . S.fromCharList
+
+instance S.StringSuperset string => S.StringSuperset (ASCII string) where
     substituteString = id
 
-instance StringSuperset string => I.StringIso (ASCII string) where
+instance S.StringSuperset string => I.StringIso (ASCII string) where
     toCharList = S.toCharListUnsafe
     mapChars = S.mapCharsUnsafe
 
@@ -85,30 +102,30 @@
 >>> map validateChar [-1, 65, 97, 128] :: [Maybe (ASCII Int)]
 [Nothing,Just (asciiUnsafe 65),Just (asciiUnsafe 97),Nothing]
 -}
-validateChar :: CharSuperset superset => superset -> Maybe (ASCII superset)
+validateChar :: S.CharSuperset superset => superset -> Maybe (ASCII superset)
 validateChar x = if S.isAsciiChar x then Just (asciiUnsafe x) else Nothing
 
-substituteChar :: CharSuperset superset => superset -> ASCII superset
+substituteChar :: S.CharSuperset superset => superset -> ASCII superset
 substituteChar x = if S.isAsciiChar x then asciiUnsafe x else fromChar ASCII.Substitute
 
-fromChar :: CharSuperset superset => ASCII.Char -> ASCII superset
+fromChar :: S.CharSuperset superset => ASCII.Char -> ASCII superset
 fromChar = asciiUnsafe . S.fromChar
 
-toChar :: CharSuperset superset => ASCII superset -> ASCII.Char
+toChar :: S.CharSuperset superset => ASCII superset -> ASCII.Char
 toChar = S.toCharUnsafe . lift
 
 {-|
 >>> fromCharList [CapitalLetterH,SmallLetterI,ExclamationMark] :: ASCII Text
 asciiUnsafe "Hi!"
 -}
-fromCharList :: StringSuperset superset => [ASCII.Char] -> ASCII superset
+fromCharList :: S.StringSuperset superset => [ASCII.Char] -> ASCII superset
 fromCharList = asciiUnsafe . S.fromCharList
 
 {-|
 >>> toCharList (substituteString "Piñata" :: ASCII Text)
 [CapitalLetterP,SmallLetterI,Substitute,SmallLetterA,SmallLetterT,SmallLetterA]
 -}
-toCharList :: StringSuperset superset => ASCII superset -> [ASCII.Char]
+toCharList :: S.StringSuperset superset => ASCII superset -> [ASCII.Char]
 toCharList = S.toCharListUnsafe . lift
 
 {-| Forces a string from a larger character set into ASCII by using the
@@ -117,7 +134,7 @@
 >>> substituteString "Cristóbal" :: ASCII Text
 asciiUnsafe "Crist\SUBbal"
 -}
-substituteString :: StringSuperset superset => superset -> ASCII superset
+substituteString :: S.StringSuperset superset => superset -> ASCII superset
 substituteString = asciiUnsafe . S.substituteString
 
 {-|
@@ -127,11 +144,11 @@
 >>> map validateString ["Hello", "Cristóbal"] :: [Maybe (ASCII String)]
 [Just (asciiUnsafe "Hello"),Nothing]
 -}
-validateString :: StringSuperset superset => superset -> Maybe (ASCII superset)
+validateString :: S.StringSuperset superset => superset -> Maybe (ASCII superset)
 validateString x = if S.isAsciiString x then Just (asciiUnsafe x) else Nothing
 
-asChar :: CharSuperset superset => (ASCII.Char -> ASCII.Char) -> ASCII superset -> ASCII superset
+asChar :: S.CharSuperset superset => (ASCII.Char -> ASCII.Char) -> ASCII superset -> ASCII superset
 asChar f = asciiUnsafe . S.asCharUnsafe f . lift
 
-mapChars :: StringSuperset superset => (ASCII.Char -> ASCII.Char) -> ASCII superset -> ASCII superset
+mapChars :: S.StringSuperset superset => (ASCII.Char -> ASCII.Char) -> ASCII superset -> ASCII superset
 mapChars f = asciiUnsafe . S.mapCharsUnsafe f . lift
diff --git a/library/ASCII/Superset.hs b/library/ASCII/Superset.hs
--- a/library/ASCII/Superset.hs
+++ b/library/ASCII/Superset.hs
@@ -1,17 +1,18 @@
 module ASCII.Superset
   (
     {- * Characters -}
-    {- ** Class -} CharSuperset (..),
-    {- ** Functions -} asCharUnsafe, toCharMaybe, toCharOrFail,
-        toCharSub, substituteChar, convertCharMaybe, convertCharOrFail,
+    {- ** Class -} ToCaselessChar (..), ToChar (..), FromChar (..), CharSuperset,
+    {- ** Functions -} asCharUnsafe, toCharMaybe, toCaselessCharMaybe, toCharOrFail, toCaselessCharOrFail,
+        toCharSub, toCaselessCharSub, substituteChar, convertCharMaybe, convertCharOrFail,
 
     {- * Strings -}
-    {- ** Class -} StringSuperset (..),
-    {- ** Functions -} toCharListMaybe, toCharListOrFail,
+    {- ** Class -} ToCaselessString (..), ToString (..), FromString (..), StringSuperset (..),
+    {- ** Functions -} toCharListMaybe, toCaselessCharListMaybe, toCharListOrFail, toCaselessCharListOrFail,
         convertStringMaybe, convertStringOrFail
   )
   where
 
+import ASCII.Caseless (CaselessChar)
 import Control.Monad (return)
 import Control.Monad.Fail (MonadFail (fail))
 import Data.Bool (Bool, (&&))
@@ -20,6 +21,7 @@
 import Data.Maybe (Maybe (..))
 import Data.Ord ((<=), (>=))
 
+import qualified ASCII.Caseless as Caseless
 import qualified ASCII.Char as ASCII
 import qualified Data.Bool as Bool
 import qualified Data.ByteString as BS
@@ -38,75 +40,181 @@
 
 ---  Char  ---
 
-class CharSuperset char where
+{-| Partial conversion to 'CaselessChar'
 
+Generally this will be a superset of the ASCII character set with a 'ToChar'
+instance as well, and the conversion will be achieved by discarding the case of
+letters. A notable exception is the instance for the 'CaselessChar' type itself,
+which is already represented without case and does not have a 'ToChar' instance.
+-}
+class ToCaselessChar char where
+
+    -- | Test whether a character can be converted to 'CaselessChar'
+    isAsciiCaselessChar :: char -> Bool
+
+    -- | Conversion to 'CaselessChar', defined only where 'isAsciiCaselessChar' is satisfied
+    toCaselessCharUnsafe :: char -> CaselessChar
+
+{-| Partial conversion to 'ASCII.Char'
+
+This includes the 'ASCII.Char' type itself, character sets that are supersets
+of ASCII, and numeric types such as 'Word8' that are often used to represent
+ASCII characters. -}
+class ToCaselessChar char => ToChar char where
+
+    -- | Test whether a character can be converted to 'ASCII.Char'
     isAsciiChar :: char -> Bool
 
+    -- | Conversion to 'ASCII.Char', defined only where 'isAsciiChar' is satisfied
+    toCharUnsafe :: char -> ASCII.Char
+
+{-| Total conversion from 'ASCII.Char'
+
+This class includes supersets of ASCII, in which case 'fromChar' is a lifting
+function. It also includes 'CaselessChar', in which case 'fromChar' discards
+case information. -}
+class FromChar char where
+
+    -- | Conversion from 'ASCII.Char'
     fromChar :: ASCII.Char -> char
 
-    toCharUnsafe :: char -> ASCII.Char
+{- | Character type with:
 
+- a total conversion from ASCII; and
+- a partial conversion to ASCII -}
+class (ToChar char, FromChar char) => CharSuperset char
+
+{-| Manipulate a character as if it were an ASCII 'ASCII.Char', assuming that it is
+
+Defined only where 'isAsciiChar' is satisfied. -}
 asCharUnsafe :: CharSuperset char => (ASCII.Char -> ASCII.Char) -> char -> char
 asCharUnsafe f = fromChar . f . toCharUnsafe
 
-toCharMaybe :: CharSuperset char => char -> Maybe ASCII.Char
+toCharMaybe :: ToChar char => char -> Maybe ASCII.Char
 toCharMaybe = toCharOrFail
 
-toCharOrFail :: (CharSuperset char, MonadFail context) => char -> context ASCII.Char
+toCaselessCharMaybe :: ToCaselessChar char => char -> Maybe CaselessChar
+toCaselessCharMaybe = toCaselessCharOrFail
+
+toCharOrFail :: (ToChar char, MonadFail context) => char -> context ASCII.Char
 toCharOrFail x = if isAsciiChar x then return (toCharUnsafe x)
     else fail "Not an ASCII character"
 
-toCharSub :: CharSuperset char => char -> ASCII.Char
+toCaselessCharOrFail :: (ToCaselessChar char, MonadFail context) => char -> context CaselessChar
+toCaselessCharOrFail x = if isAsciiCaselessChar x then return (toCaselessCharUnsafe x)
+    else fail "Not an ASCII character"
+
+toCharSub :: ToChar char => char -> ASCII.Char
 toCharSub x = if isAsciiChar x then toCharUnsafe x else ASCII.Substitute
 
+toCaselessCharSub :: ToCaselessChar char => char -> CaselessChar
+toCaselessCharSub x = if isAsciiCaselessChar x then toCaselessCharUnsafe x else Caseless.Substitute
+
+{-| Force a character into ASCII by replacing it with 'ASCII.Substitute' if it
+    is not already an ASCII character
+
+The resulting character satisfies 'isAsciiChar' and 'isAsciiCaselessChar'. -}
 substituteChar :: CharSuperset char => char -> char
 substituteChar x = if isAsciiChar x then x else fromChar ASCII.Substitute
 
 {-| Convert from one ASCII-superset character type to another via the ASCII
 'ASCII.Char' type. Fails as 'Nothing' if the input is outside the ASCII
 character set. -}
-convertCharMaybe :: (CharSuperset char1, CharSuperset char2) =>
-    char1 -> Maybe char2
+convertCharMaybe :: (ToChar char1, FromChar char2) => char1 -> Maybe char2
 convertCharMaybe = convertCharOrFail
 
 {-| Convert from one ASCII-superset character type to another via the ASCII
 'ASCII.Char' type. Fails with 'fail' if the input is outside the ASCII character
 set. -}
-convertCharOrFail :: (CharSuperset char1, CharSuperset char2, MonadFail context) =>
+convertCharOrFail :: (ToChar char1, FromChar char2, MonadFail context) =>
     char1 -> context char2
 convertCharOrFail = fmap fromChar . toCharOrFail
 
 
 ---  String  ---
 
-class StringSuperset string where
+{-| Partial conversion to @['CaselessChar']@
 
-    isAsciiString :: string -> Bool
+Generally this will be a superset of ASCII strings with a 'ToString' instance as
+well, and the conversion will be achieved by discarding the case of letters. A
+notable exception is the instance for @['CaselessChar']@ type itself, which is
+already represented without case and does not have a 'ToString' instance. -}
+class ToCaselessString string where
 
-    fromCharList :: [ASCII.Char] -> string
+    -- | Test whether a character can be converted to @['CaselessChar']@
+    isAsciiCaselessString :: string -> Bool
 
+    {-| Conversion to @['CaselessChar']@, defined only where
+        'isAsciiCaselessString' is satisfied -}
+    toCaselessCharListUnsafe :: string -> [CaselessChar]
+
+    {-| Conversion to @['CaselessChar']@ achieved by using
+        'Caseless.Substitute' in place of any non-ASCII characters -}
+    toCaselessCharListSub :: string -> [CaselessChar]
+
+{-| Partial conversion to @['ASCII.Char']@
+
+This includes @['ASCII.Char']@ type itself, strings of character sets that are
+supersets of ASCII, and sequences of numeric types such as 'Word8' that are
+often used to represent ASCII characters. -}
+class ToCaselessString string => ToString string where
+
+    -- | Test whether a string can be converted to @['ASCII.Char']@
+    isAsciiString :: string -> Bool
+
+    {-| Conversion to @['ASCII.Char']@, defined only where 'isAsciiString'
+        is satisfied -}
     toCharListUnsafe :: string -> [ASCII.Char]
 
+    {-| Conversion to @['ASCII.Char']@ achieved by using
+        'ASCII.Substitute' in place of any non-ASCII characters -}
     toCharListSub :: string -> [ASCII.Char]
 
+{-| Total conversion from @['ASCII.Char']@
+
+This class includes supersets of ASCII, in which case 'fromCharList' lifts each
+character into the larger character set. It also includes @['CaselessChar']@, in
+which case 'fromCharList' discards case information from letters. -}
+class FromString string where
+
+    -- | Conversion from @['ASCII.Char']@
+    fromCharList :: [ASCII.Char] -> string
+
+{- | String type with:
+
+- a total conversion from ASCII; and
+- a partial conversion to ASCII -}
+class (ToString string, FromString string) => StringSuperset string where
+
+    {-| Force a string into ASCII by replacing any non-ASCII character with 'ASCII.Substitute'
+
+        The resulting string satisfies 'isAsciiString' and 'isAsciiCaselessString'. -}
     substituteString :: string -> string
 
     mapCharsUnsafe :: (ASCII.Char -> ASCII.Char) -> string -> string
     mapCharsUnsafe f = fromCharList  . List.map f . toCharListUnsafe
 
-toCharListMaybe :: StringSuperset string => string -> Maybe [ASCII.Char]
+toCharListMaybe :: ToString string => string -> Maybe [ASCII.Char]
 toCharListMaybe = toCharListOrFail
 
-toCharListOrFail :: (StringSuperset string, MonadFail context) =>
+toCaselessCharListMaybe :: ToCaselessString string => string -> Maybe [CaselessChar]
+toCaselessCharListMaybe = toCaselessCharListOrFail
+
+toCharListOrFail :: (ToString string, MonadFail context) =>
     string -> context [ASCII.Char]
 toCharListOrFail x = if isAsciiString x then return (toCharListUnsafe x)
     else fail "String contains non-ASCII characters"
 
+toCaselessCharListOrFail :: (ToCaselessString string, MonadFail context) =>
+    string -> context [CaselessChar]
+toCaselessCharListOrFail x = if isAsciiCaselessString x then return (toCaselessCharListUnsafe x)
+    else fail "String contains non-ASCII characters"
+
 {-| Convert from one ASCII-superset string type to another by converting each
 character of the input string to an ASCII 'ASCII.Char', and then converting the
 ASCII character list to the desired output type. Fails as 'Nothing' if the input
 contains any character that is outside the ASCII character set. -}
-convertStringMaybe :: (StringSuperset string1, StringSuperset string2) =>
+convertStringMaybe :: (ToString string1, FromString string2) =>
     string1 -> Maybe string2
 convertStringMaybe = convertStringOrFail
 
@@ -114,90 +222,222 @@
 character of the input string to an ASCII 'ASCII.Char', and then converting the
 ASCII character list to the desired output type. Fails with 'fail' if the input
 contains any character that is outside the ASCII character set. -}
-convertStringOrFail :: (StringSuperset string1, StringSuperset string2, MonadFail context) =>
+convertStringOrFail :: (ToString string1, FromString string2, MonadFail context) =>
     string1 -> context string2
 convertStringOrFail = fmap fromCharList . toCharListOrFail
 
 
 ---  Instances  ---
 
--- | 'ASCII.Char' is trivially a superset of itself. (This instance is uninteresting.)
-instance CharSuperset ASCII.Char where
+-- | 'CaselessChar' is trivially convertible to itself. (This instance is uninteresting.)
+instance ToCaselessChar CaselessChar where
+    isAsciiCaselessChar _ = Bool.True
+    toCaselessCharUnsafe = id
+
+---
+
+instance ToCaselessChar ASCII.Char where
+    isAsciiCaselessChar _ = Bool.True
+    toCaselessCharUnsafe = Caseless.disregardCase
+
+instance ToChar ASCII.Char where
     isAsciiChar _ = Bool.True
-    fromChar = id
     toCharUnsafe = id
 
-instance CharSuperset Unicode.Char where
+instance FromChar ASCII.Char where
+    fromChar = id
+
+-- | 'ASCII.Char' is trivially a superset of itself. (This instance is uninteresting.)
+instance CharSuperset ASCII.Char
+
+---
+
+instance ToCaselessChar Unicode.Char where
+    isAsciiCaselessChar = isAsciiChar
+    toCaselessCharUnsafe = toCaselessCharUnsafe . toCharUnsafe
+
+instance ToChar Unicode.Char where
     isAsciiChar = (<= '\DEL')
+    toCharUnsafe = toCharUnsafe @Int.Int . Unicode.ord
+
+instance FromChar Unicode.Char where
     fromChar = Unicode.chr . ASCII.toInt
-    toCharUnsafe = ASCII.fromIntUnsafe . Unicode.ord
 
-instance CharSuperset Nat.Natural where
+instance CharSuperset Unicode.Char
+
+---
+
+instance ToCaselessChar Nat.Natural where
+    isAsciiCaselessChar = isAsciiChar
+    toCaselessCharUnsafe = toCaselessCharUnsafe . toCharUnsafe
+
+instance ToChar Nat.Natural where
     isAsciiChar = (<= 127)
+    toCharUnsafe = toCharUnsafe @Int.Int . Prelude.fromIntegral
+
+instance FromChar Nat.Natural where
     fromChar = Prelude.fromIntegral . ASCII.toInt
-    toCharUnsafe = ASCII.fromIntUnsafe . Prelude.fromIntegral
 
-instance CharSuperset Int.Int where
+instance CharSuperset Nat.Natural
+
+---
+
+instance ToCaselessChar Int.Int where
+    isAsciiCaselessChar = isAsciiChar
+    toCaselessCharUnsafe = toCaselessCharUnsafe . toCharUnsafe
+
+instance ToChar Int.Int where
     isAsciiChar x = (x >= 0) && (x <= 127)
-    fromChar = ASCII.toInt
     toCharUnsafe = ASCII.fromIntUnsafe
 
-instance CharSuperset Word.Word8 where
+instance FromChar Int.Int where
+    fromChar = ASCII.toInt
+
+instance CharSuperset Int.Int
+
+---
+
+instance ToCaselessChar Word.Word8 where
+    isAsciiCaselessChar = isAsciiChar
+    toCaselessCharUnsafe = toCaselessCharUnsafe . toCharUnsafe
+
+instance ToChar Word.Word8 where
     isAsciiChar = (<= 127)
-    fromChar = Prelude.fromIntegral . ASCII.toInt
     toCharUnsafe = ASCII.fromIntUnsafe . Prelude.fromIntegral
 
-instance CharSuperset char => StringSuperset [char] where
-    isAsciiString = List.all isAsciiChar
-    fromCharList = List.map fromChar
+instance FromChar Word.Word8 where
+    fromChar = Prelude.fromIntegral . ASCII.toInt
+
+instance CharSuperset Word.Word8
+
+---
+
+instance ToCaselessChar char => ToCaselessString [char] where
+    isAsciiCaselessString    = List.all isAsciiCaselessChar
+    toCaselessCharListUnsafe = List.map toCaselessCharUnsafe
+    toCaselessCharListSub    = List.map toCaselessCharSub
+
+instance ToChar char => ToString [char] where
+    isAsciiString    = List.all isAsciiChar
     toCharListUnsafe = List.map toCharUnsafe
-    toCharListSub = List.map toCharSub
+    toCharListSub    = List.map toCharSub
+
+instance FromChar char => FromString [char] where
+    fromCharList = List.map fromChar
+
+instance CharSuperset char => StringSuperset [char] where
     substituteString = List.map substituteChar
 
-instance StringSuperset T.Text where
+---
+
+instance ToCaselessString T.Text where
+    isAsciiCaselessString = T.all isAsciiChar
+    toCaselessCharListUnsafe = toCaselessCharListUnsafe . T.unpack
+    toCaselessCharListSub    = toCaselessCharListSub    . T.unpack
+
+instance ToString T.Text where
     isAsciiString = T.all isAsciiChar
-    fromCharList = T.pack . fromCharList
     toCharListUnsafe = toCharListUnsafe . T.unpack
     toCharListSub = toCharListSub . T.unpack
+
+instance FromString T.Text where
+    fromCharList = T.pack . fromCharList
+
+instance StringSuperset T.Text where
     substituteString = T.map substituteChar
     mapCharsUnsafe f = T.map (asCharUnsafe f)
 
-instance StringSuperset LT.Text where
+---
+
+instance ToCaselessString LT.Text where
+    isAsciiCaselessString = LT.all isAsciiChar
+    toCaselessCharListUnsafe = toCaselessCharListUnsafe . LT.unpack
+    toCaselessCharListSub    = toCaselessCharListSub    . LT.unpack
+
+instance ToString LT.Text where
     isAsciiString = LT.all isAsciiChar
-    fromCharList = LT.pack . fromCharList
     toCharListUnsafe = toCharListUnsafe . LT.unpack
-    toCharListSub = toCharListSub . LT.unpack
+    toCharListSub    = toCharListSub    . LT.unpack
+
+instance FromString LT.Text where
+    fromCharList = LT.pack . fromCharList
+
+instance StringSuperset LT.Text where
     substituteString = LT.map substituteChar
     mapCharsUnsafe f = LT.map (asCharUnsafe f)
 
-instance StringSuperset TB.Builder where
-    isAsciiString = isAsciiString . TB.toLazyText
-    fromCharList = TB.fromString . fromCharList
+---
+
+instance ToCaselessString TB.Builder where
+    isAsciiCaselessString    = isAsciiCaselessString    . TB.toLazyText
+    toCaselessCharListUnsafe = toCaselessCharListUnsafe . TB.toLazyText
+    toCaselessCharListSub    = toCaselessCharListSub    . TB.toLazyText
+
+instance ToString TB.Builder where
+    isAsciiString    = isAsciiString    . TB.toLazyText
     toCharListUnsafe = toCharListUnsafe . TB.toLazyText
-    toCharListSub = toCharListSub . TB.toLazyText
+    toCharListSub    = toCharListSub    . TB.toLazyText
+
+instance FromString TB.Builder where
+    fromCharList = TB.fromString . fromCharList
+
+instance StringSuperset TB.Builder where
     substituteString = TB.fromLazyText . substituteString . TB.toLazyText
     mapCharsUnsafe f = TB.fromLazyText . mapCharsUnsafe f . TB.toLazyText
 
-instance StringSuperset BS.ByteString where
+---
+
+instance ToCaselessString BS.ByteString where
+    isAsciiCaselessString = BS.all isAsciiCaselessChar
+    toCaselessCharListUnsafe = toCaselessCharListUnsafe . BS.unpack
+    toCaselessCharListSub    = toCaselessCharListSub    . BS.unpack
+
+instance ToString BS.ByteString where
     isAsciiString = BS.all isAsciiChar
-    fromCharList = BS.pack . fromCharList
     toCharListUnsafe = toCharListUnsafe . BS.unpack
-    toCharListSub = toCharListSub . BS.unpack
+    toCharListSub    = toCharListSub    . BS.unpack
+
+instance FromString BS.ByteString where
+    fromCharList = BS.pack . fromCharList
+
+instance StringSuperset BS.ByteString where
     substituteString = BS.map substituteChar
     mapCharsUnsafe f = BS.map (asCharUnsafe f)
 
-instance StringSuperset LBS.ByteString where
+---
+
+instance ToCaselessString LBS.ByteString where
+    isAsciiCaselessString = LBS.all isAsciiCaselessChar
+    toCaselessCharListUnsafe = toCaselessCharListUnsafe . LBS.unpack
+    toCaselessCharListSub    = toCaselessCharListSub    . LBS.unpack
+
+instance ToString LBS.ByteString where
     isAsciiString = LBS.all isAsciiChar
-    fromCharList = LBS.pack . fromCharList
     toCharListUnsafe = toCharListUnsafe . LBS.unpack
-    toCharListSub = toCharListSub . LBS.unpack
+    toCharListSub    = toCharListSub    . LBS.unpack
+
+instance FromString LBS.ByteString where
+    fromCharList = LBS.pack . fromCharList
+
+instance StringSuperset LBS.ByteString where
     substituteString = LBS.map substituteChar
     mapCharsUnsafe f = LBS.map (asCharUnsafe f)
 
-instance StringSuperset BSB.Builder where
-    isAsciiString = isAsciiString . BSB.toLazyByteString
-    fromCharList = BSB.lazyByteString . fromCharList
+---
+
+instance ToCaselessString BSB.Builder where
+    isAsciiCaselessString    = isAsciiCaselessString    . BSB.toLazyByteString
+    toCaselessCharListUnsafe = toCaselessCharListUnsafe . BSB.toLazyByteString
+    toCaselessCharListSub    = toCaselessCharListSub    . BSB.toLazyByteString
+
+instance ToString BSB.Builder where
+    isAsciiString    = isAsciiString    . BSB.toLazyByteString
     toCharListUnsafe = toCharListUnsafe . BSB.toLazyByteString
-    toCharListSub = toCharListSub . BSB.toLazyByteString
+    toCharListSub    = toCharListSub    . BSB.toLazyByteString
+
+instance FromString BSB.Builder where
+    fromCharList = BSB.lazyByteString . fromCharList
+
+instance StringSuperset BSB.Builder where
     substituteString = BSB.lazyByteString . substituteString . BSB.toLazyByteString
     mapCharsUnsafe f = BSB.lazyByteString . mapCharsUnsafe f . BSB.toLazyByteString
