packages feed

ascii-superset 1.3.0.0 → 1.3.0.1

raw patch · 12 files changed

+920/−785 lines, 12 filesdep ~basedep ~hspecPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: base, hspec

API changes (from Hackage documentation)

- ASCII.CaseRefinement: data ASCII'case (letterCase :: Case) superset
+ ASCII.CaseRefinement: data ASCII'case (letterCase :: Case) (superset :: Type)
- ASCII.Isomorphism: class CharSuperset char => CharIso char
+ ASCII.Isomorphism: class CharSuperset (char :: Type) => CharIso char
- ASCII.Isomorphism: class StringSuperset string => StringIso string
+ ASCII.Isomorphism: class StringSuperset string => StringIso (string :: Type)
- ASCII.Refinement: data ASCII superset
+ ASCII.Refinement: data ASCII (superset :: Type)
- ASCII.Superset: class (ToChar char, FromChar char) => CharSuperset char
+ ASCII.Superset: class (ToChar char, FromChar char) => CharSuperset (char :: Type)
- ASCII.Superset: class FromChar char
+ ASCII.Superset: class FromChar (char :: Type)
- ASCII.Superset: class FromString string
+ ASCII.Superset: class FromString (string :: Type)
- ASCII.Superset: class (ToString string, FromString string) => StringSuperset string
+ ASCII.Superset: class (ToString string, FromString string) => StringSuperset (string :: Type)
- ASCII.Superset: class ToCasefulChar (letterCase :: Case) char
+ ASCII.Superset: class ToCasefulChar (letterCase :: Case) (char :: Type)
- ASCII.Superset: class ToCasefulString (letterCase :: Case) string
+ ASCII.Superset: class ToCasefulString (letterCase :: Case) (string :: Type)
- ASCII.Superset: class ToCaselessChar char
+ ASCII.Superset: class ToCaselessChar (char :: Type)
- ASCII.Superset: class ToCaselessString string
+ ASCII.Superset: class ToCaselessString (string :: Type)
- ASCII.Superset: class ToCaselessChar char => ToChar char
+ ASCII.Superset: class ToCaselessChar char => ToChar (char :: Type)
- ASCII.Superset: class ToCaselessString string => ToString string
+ ASCII.Superset: class ToCaselessString string => ToString (string :: Type)
- ASCII.Superset.Text: class ToText a
+ ASCII.Superset.Text: class ToText (a :: Type)
- ASCII.SupersetConversion: class (StringSuperset a, StringSuperset b) => StringSupersetConversion a b
+ ASCII.SupersetConversion: class (StringSuperset a, StringSuperset b) => StringSupersetConversion (a :: Type) (b :: Type)

Files

ascii-superset.cabal view
@@ -1,7 +1,7 @@ cabal-version: 3.0  name: ascii-superset-version: 1.3.0.0+version: 1.3.0.1 synopsis: Representing ASCII with refined supersets category: Data, Text @@ -26,7 +26,7 @@     location: git://github.com/typeclasses/ascii-superset.git  common base-    default-language: Haskell2010+    default-language: GHC2021     ghc-options: -Wall      default-extensions:@@ -45,7 +45,7 @@       , ascii-case ^>= 1.0.1       , ascii-caseless ^>= 0.0.0       , ascii-char ^>= 1.0-      , base ^>= 4.14 || ^>= 4.15 || ^>= 4.16 || ^>= 4.17+      , base ^>= 4.16 || ^>= 4.17 || ^>= 4.18       , text ^>= 1.2.4 || ^>= 2.0  library@@ -87,4 +87,4 @@      build-depends:       , ascii-superset-      , hspec ^>= 2.8.5 || ^>= 2.9 || ^>= 2.10+      , hspec ^>= 2.9.7 || ^>= 2.10 || ^>= 2.11
changelog.md view
@@ -1,3 +1,7 @@+### 1.3.0.1 (2023-06-26)++Raised language version to GHC2021.+ ### 1.3.0.0 (2023-02-28)  Removed the `ASCII.Lift` module. The `Lift` class is now gone. It was a mess. It
library/ASCII/CaseRefinement.hs view
@@ -1,116 +1,143 @@ module ASCII.CaseRefinement-  (-    {- * ASCII'case type constructor -} ASCII'case, lift, asciiCaseUnsafe, forgetCase,-    {- ** Aliases -} {- $aliases -} ASCII'upper, ASCII'lower,-    {- * Character functions -} validateChar, fromCaselessChar,-          toCaselessChar, substituteChar, asCaselessChar, refineCharToCase,-    {- * String functions -} validateString, fromCaselessCharList,-          toCaselessCharList, substituteString, mapChars, refineStringToCase,-    {- * KnownCase -} KnownCase (..),+  ( -- * ASCII'case type constructor+    ASCII'case,+    lift,+    asciiCaseUnsafe,+    forgetCase,++    -- ** Aliases+    -- $aliases+    ASCII'upper,+    ASCII'lower,++    -- * Character functions+    validateChar,+    fromCaselessChar,+    toCaselessChar,+    substituteChar,+    asCaselessChar,+    refineCharToCase,++    -- * String functions+    validateString,+    fromCaselessCharList,+    toCaselessCharList,+    substituteString,+    mapChars,+    refineStringToCase,++    -- * KnownCase+    KnownCase (..),   )-  where+where  import ASCII.Case (Case (..))+import ASCII.Case qualified as Case import ASCII.Caseless (CaselessChar)-import {-# source #-} ASCII.Refinement.Internal (ASCII)+import ASCII.Caseless qualified as Caseless+import ASCII.Char qualified as ASCII+import {-# SOURCE #-} ASCII.Refinement.Internal (ASCII)+import {-# SOURCE #-} ASCII.Refinement.Internal qualified as Refinement import ASCII.Superset (CharSuperset, StringSuperset)--import qualified ASCII.Case as Case-import qualified ASCII.Caseless as Caseless-import qualified ASCII.Char as ASCII-import qualified ASCII.Superset as S-import {-# source #-} qualified ASCII.Refinement.Internal as Refinement-+import ASCII.Superset qualified as S import Control.Monad (guard)+import Data.Bool qualified as Bool import Data.Data (Data, Typeable) import Data.Eq (Eq) import Data.Foldable (any) import Data.Function (($), (.)) import Data.Hashable (Hashable)+import Data.Kind (Type)+import Data.List qualified as List import Data.Maybe (Maybe (..)) import Data.Monoid (Monoid) import Data.Ord (Ord, (>)) 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 Data.List as List--{-| Indicates that a value from some ASCII superset is valid ASCII, and also-    that any letters belong to a particular 'Case' indicated by the @letterCase@-    type parameter--The @superset@ type parameter is the ASCII superset, which should be a type with-an instance of either 'CharSuperset' or 'StringSuperset'.+import Prelude (succ) -For example, whereas a 'Data.Text.Text' value may contain a combination of ASCII-and non-ASCII characters, a value of type @'ASCII'case' ''ASCII.Case.UpperCase'-'Data.Text.Text'@ may contain only uppercase ASCII letters and ASCII-non-letters. -}-newtype ASCII'case (letterCase :: Case) superset = ASCII'case_Unsafe-  { lift :: superset-      {- ^ Discard the evidence that the value is known to consist-           entirely of ASCII characters in a particular case -}+-- | Indicates that a value from some ASCII superset is valid ASCII, and also+--    that any letters belong to a particular 'Case' indicated by the @letterCase@+--    type parameter+--+-- The @superset@ type parameter is the ASCII superset, which should be a type with+-- an instance of either 'CharSuperset' or 'StringSuperset'.+--+-- For example, whereas a 'Data.Text.Text' value may contain a combination of ASCII+-- and non-ASCII characters, a value of type @'ASCII'case' ''ASCII.Case.UpperCase'+-- 'Data.Text.Text'@ may contain only uppercase ASCII letters and ASCII+-- non-letters.+newtype ASCII'case (letterCase :: Case) (superset :: Type) = ASCII'case_Unsafe+  { -- | Discard the evidence that the value is known to consist+    --           entirely of ASCII characters in a particular case+    lift :: superset   } -deriving stock instance Eq superset =>-    Eq (ASCII'case letterCase superset)+deriving stock instance+  Eq superset =>+  Eq (ASCII'case letterCase superset) -deriving stock instance Ord superset =>-    Ord (ASCII'case letterCase superset)+deriving stock instance+  Ord superset =>+  Ord (ASCII'case letterCase superset) -deriving newtype instance Hashable superset =>-    Hashable (ASCII'case letterCase superset)+deriving newtype instance+  Hashable superset =>+  Hashable (ASCII'case letterCase superset) -deriving newtype instance Semigroup superset =>-    Semigroup (ASCII'case letterCase superset)+deriving newtype instance+  Semigroup superset =>+  Semigroup (ASCII'case letterCase superset) -deriving newtype instance Monoid superset =>-    Monoid (ASCII'case letterCase superset)+deriving newtype instance+  Monoid superset =>+  Monoid (ASCII'case letterCase superset) -deriving stock instance (Data superset, Typeable letterCase) =>-    Data (ASCII'case letterCase superset)+deriving stock instance+  (Data superset, Typeable letterCase) =>+  Data (ASCII'case letterCase superset)  deriving stock instance Generic (ASCII'case letterCase superset)  instance Show superset => Show (ASCII'case letterCase superset) where-    showsPrec d x = showParen (d > app_prec) $-        showString "asciiCaseUnsafe " . showsPrec (succ app_prec) (lift x)-      where app_prec = 10+  showsPrec d x =+    showParen (d > app_prec) $+      showString "asciiCaseUnsafe " . showsPrec (succ app_prec) (lift x)+    where+      app_prec = 10 -    showList x = showString "asciiCaseUnsafe " . showList (List.map lift x)+  showList x = showString "asciiCaseUnsafe " . showList (List.map lift x)  instance S.ToCaselessChar char => S.ToCaselessChar (ASCII'case letterCase char) where-    isAsciiCaselessChar _ = Bool.True-    toCaselessCharUnsafe = S.toCaselessCharUnsafe . lift+  isAsciiCaselessChar _ = Bool.True+  toCaselessCharUnsafe = S.toCaselessCharUnsafe . lift  instance S.CharSuperset char => S.ToChar (ASCII'case letterCase char) where-    isAsciiChar _ = Bool.True-    toCharUnsafe = S.toCharUnsafe . lift+  isAsciiChar _ = Bool.True+  toCharUnsafe = S.toCharUnsafe . lift  instance S.ToCaselessString string => S.ToCaselessString (ASCII'case letterCase string) where-    isAsciiCaselessString _ = Bool.True-    toCaselessCharListUnsafe = S.toCaselessCharListUnsafe . lift-    toCaselessCharListSub = S.toCaselessCharListSub . lift+  isAsciiCaselessString _ = Bool.True+  toCaselessCharListUnsafe = S.toCaselessCharListUnsafe . lift+  toCaselessCharListSub = S.toCaselessCharListSub . lift  instance S.ToString string => S.ToString (ASCII'case letterCase string) where-    isAsciiString _ = Bool.True-    toCharListUnsafe = S.toCharListUnsafe . lift-    toCharListSub = S.toCharListUnsafe . lift+  isAsciiString _ = Bool.True+  toCharListUnsafe = S.toCharListUnsafe . lift+  toCharListSub = S.toCharListUnsafe . lift  instance (S.FromChar superset, KnownCase letterCase) => S.ToCasefulChar letterCase (ASCII'case letterCase superset) where-    toCasefulChar = asciiCaseUnsafe . S.fromChar . Caseless.toCase (theCase @letterCase)+  toCasefulChar = asciiCaseUnsafe . S.fromChar . Caseless.toCase (theCase @letterCase)  instance (S.FromString superset, KnownCase letterCase) => S.ToCasefulString letterCase (ASCII'case letterCase superset) where-    toCasefulString = asciiCaseUnsafe . S.fromCharList . List.map (Caseless.toCase (theCase @letterCase))--{-| Change the type of an ASCII superset value that is known to be valid ASCII where-    letters are restricted to the 'Case' designated by the @letterCase@ type variable+  toCasefulString = asciiCaseUnsafe . S.fromCharList . List.map (Caseless.toCase (theCase @letterCase)) -This is "unsafe" because this assertion is unchecked, so this function is capable-of producing an invalid 'ASCII'case' value. -}+-- | Change the type of an ASCII superset value that is known to be valid ASCII where+--    letters are restricted to the 'Case' designated by the @letterCase@ type variable+--+-- This is "unsafe" because this assertion is unchecked, so this function is capable+-- of producing an invalid 'ASCII'case' value. asciiCaseUnsafe :: superset -> ASCII'case letterCase superset asciiCaseUnsafe = ASCII'case_Unsafe @@ -119,10 +146,11 @@  --- -{- $aliases+-- $aliases+--+-- The 'ASCII'upper' and 'ASCII'lower' type aliases exist primarily so that you can+-- use 'ASCII'case' without the DataKinds language extension. -The 'ASCII'upper' and 'ASCII'lower' type aliases exist primarily so that you can-use 'ASCII'case' without the DataKinds language extension. -} type ASCII'upper superset = ASCII'case 'UpperCase superset  type ASCII'lower superset = ASCII'case 'LowerCase superset@@ -130,115 +158,165 @@ ---  class KnownCase (letterCase :: Case) where theCase :: Case+ instance KnownCase 'UpperCase where theCase = UpperCase+ instance KnownCase 'LowerCase where theCase = LowerCase  --- -{-| Return 'Just' an 'ASCII'case' character if the input is an ASCII character-    in the proper case, or 'Nothing' otherwise -}-validateChar :: forall letterCase superset. KnownCase letterCase => CharSuperset superset =>-    superset {- ^ Character which may or may not be in the ASCII character set;-                  if a letter, may be in any case -}-    -> Maybe (ASCII'case letterCase superset)+-- | Return 'Just' an 'ASCII'case' character if the input is an ASCII character+--    in the proper case, or 'Nothing' otherwise+validateChar ::+  forall letterCase superset.+  KnownCase letterCase =>+  CharSuperset superset =>+  -- | Character which may or may not be in the ASCII character set;+  --                  if a letter, may be in any case+  superset ->+  Maybe (ASCII'case letterCase superset) validateChar x = do-    c <- S.toCharMaybe x-    guard (Bool.not (Case.isCase (Case.opposite (theCase @letterCase)) c))-    Just (asciiCaseUnsafe x)+  c <- S.toCharMaybe x+  guard (Bool.not (Case.isCase (Case.opposite (theCase @letterCase)) c))+  Just (asciiCaseUnsafe x) -{-| Return an 'ASCII'case' character if the input is an ASCII character in the-    proper case, or 'ASCII.Substitute' otherwise -}-substituteChar :: forall letterCase superset. KnownCase letterCase => CharSuperset superset =>-    superset-    -> ASCII'case letterCase superset+-- | Return an 'ASCII'case' character if the input is an ASCII character in the+--    proper case, or 'ASCII.Substitute' otherwise+substituteChar ::+  forall letterCase superset.+  KnownCase letterCase =>+  CharSuperset superset =>+  superset ->+  ASCII'case letterCase superset substituteChar x = case validateChar x of-    Nothing -> asciiCaseUnsafe (S.fromChar ASCII.Substitute)-    Just c -> c+  Nothing -> asciiCaseUnsafe (S.fromChar ASCII.Substitute)+  Just c -> c -{-| Lift a 'CaselessChar' into a superset type, wrapped in the 'ASCII'case'-    refinement to save the evidence that it is ASCII in a particular case -}-fromCaselessChar :: forall letterCase superset. KnownCase letterCase => CharSuperset superset =>-    CaselessChar -- ^ Character which, if it is a letter, does not have a specified case-    -> ASCII'case letterCase superset+-- | Lift a 'CaselessChar' into a superset type, wrapped in the 'ASCII'case'+--    refinement to save the evidence that it is ASCII in a particular case+fromCaselessChar ::+  forall letterCase superset.+  KnownCase letterCase =>+  CharSuperset superset =>+  -- | Character which, if it is a letter, does not have a specified case+  CaselessChar ->+  ASCII'case letterCase superset fromCaselessChar = asciiCaseUnsafe . S.fromChar . Caseless.toCase (theCase @letterCase) -{-| Given a character from some type that is known to represent an ASCII-    character in a particular case, obtain the caseless ASCII character-    it represents -}-toCaselessChar :: CharSuperset superset =>-    ASCII'case letterCase superset {- ^ Character that is known to be ASCII, and-                                        in the particular case if it is a letter -}-    -> CaselessChar+-- | Given a character from some type that is known to represent an ASCII+--    character in a particular case, obtain the caseless ASCII character+--    it represents+toCaselessChar ::+  CharSuperset superset =>+  -- | Character that is known to be ASCII, and+  --                                        in the particular case if it is a letter+  ASCII'case letterCase superset ->+  CaselessChar toCaselessChar = Caseless.disregardCase . S.toCharUnsafe . lift -{-| Given a character from a larger set that is known to represent an ASCII-    character, manipulate it as if it were an ASCII character -}-asCaselessChar :: forall letterCase superset. KnownCase letterCase => CharSuperset superset =>-    (CaselessChar -> CaselessChar) -- ^ Case-insensitive function over ASCII characters-    -> ASCII'case letterCase superset {- ^ Character that is known to be ASCII, and-                                           in the particular case if it is a letter -}-    -> ASCII'case letterCase superset+-- | Given a character from a larger set that is known to represent an ASCII+--    character, manipulate it as if it were an ASCII character+asCaselessChar ::+  forall letterCase superset.+  KnownCase letterCase =>+  CharSuperset superset =>+  -- | Case-insensitive function over ASCII characters+  (CaselessChar -> CaselessChar) ->+  -- | Character that is known to be ASCII, and+  --                                           in the particular case if it is a letter+  ASCII'case letterCase superset ->+  ASCII'case letterCase superset asCaselessChar f = asciiCaseUnsafe . S.asCharUnsafe g . lift   where     g = Caseless.toCase (theCase @letterCase) . f . Caseless.assumeCaseUnsafe (theCase @letterCase) -{-| Given an ASCII superset character that is known to be valid ASCII,-    refine it further by converting it to a particular letter case -}-refineCharToCase :: forall letterCase char. KnownCase letterCase => CharSuperset char =>-    ASCII char -> ASCII'case letterCase char+-- | Given an ASCII superset character that is known to be valid ASCII,+--    refine it further by converting it to a particular letter case+refineCharToCase ::+  forall letterCase char.+  KnownCase letterCase =>+  CharSuperset char =>+  ASCII char ->+  ASCII'case letterCase char refineCharToCase = asciiCaseUnsafe . S.toCaseChar (theCase @letterCase) . Refinement.lift  --- -{-| Return 'Just' an 'ASCII'case' string if the input consists entirely of ASCII-    characters in the proper case, or 'Nothing' otherwise -}-validateString :: forall letterCase superset. KnownCase letterCase => StringSuperset superset =>-    superset -- ^ String which may or may not be valid ASCII, where letters may be in any case-    -> Maybe (ASCII'case letterCase superset)+-- | Return 'Just' an 'ASCII'case' string if the input consists entirely of ASCII+--    characters in the proper case, or 'Nothing' otherwise+validateString ::+  forall letterCase superset.+  KnownCase letterCase =>+  StringSuperset superset =>+  -- | String which may or may not be valid ASCII, where letters may be in any case+  superset ->+  Maybe (ASCII'case letterCase superset) validateString x = do-    s <- S.toCharListMaybe x-    guard (Bool.not (any (Case.isCase (Case.opposite (theCase @letterCase))) s))-    Just (asciiCaseUnsafe x)+  s <- S.toCharListMaybe x+  guard (Bool.not (any (Case.isCase (Case.opposite (theCase @letterCase))) s))+  Just (asciiCaseUnsafe x) -{-| Lift a list of 'CaselessChar' into a superset string type, wrapped in the-    'ASCII'case' refinement to save the evidence that all of the characters in-    the string are ASCII in a particular case -}-fromCaselessCharList :: forall letterCase superset. KnownCase letterCase => StringSuperset superset =>-    [CaselessChar] -- ^ Case-insensitive ASCII string represented as a list of caseless characters-    -> ASCII'case letterCase superset+-- | Lift a list of 'CaselessChar' into a superset string type, wrapped in the+--    'ASCII'case' refinement to save the evidence that all of the characters in+--    the string are ASCII in a particular case+fromCaselessCharList ::+  forall letterCase superset.+  KnownCase letterCase =>+  StringSuperset superset =>+  -- | Case-insensitive ASCII string represented as a list of caseless characters+  [CaselessChar] ->+  ASCII'case letterCase superset fromCaselessCharList = asciiCaseUnsafe . S.fromCharList . List.map (Caseless.toCase (theCase @letterCase)) -{-| Given a string from some type that is known to represent only ASCII characters-    in a particular case, obtain the caseless characters it represents -}-toCaselessCharList :: forall letterCase superset. KnownCase letterCase => StringSuperset superset =>-    ASCII'case letterCase superset -- ^ String that is known to be valid ASCII in a particular case-    -> [CaselessChar]+-- | Given a string from some type that is known to represent only ASCII characters+--    in a particular case, obtain the caseless characters it represents+toCaselessCharList ::+  forall letterCase superset.+  KnownCase letterCase =>+  StringSuperset superset =>+  -- | String that is known to be valid ASCII in a particular case+  ASCII'case letterCase superset ->+  [CaselessChar] toCaselessCharList = List.map (Caseless.assumeCaseUnsafe (theCase @letterCase)) . S.toCharListUnsafe . lift -{-| Forces a string from a larger character set into cased ASCII by using the-    'ASCII.Substitute' character in place of any unacceptable characters -}-substituteString :: forall letterCase superset. KnownCase letterCase => StringSuperset superset =>-    superset -- ^ String which may or may not be valid ASCII, where letters may be in any case-    -> ASCII'case letterCase superset+-- | Forces a string from a larger character set into cased ASCII by using the+--    'ASCII.Substitute' character in place of any unacceptable characters+substituteString ::+  forall letterCase superset.+  KnownCase letterCase =>+  StringSuperset superset =>+  -- | String which may or may not be valid ASCII, where letters may be in any case+  superset ->+  ASCII'case letterCase superset substituteString = asciiCaseUnsafe . S.fromCharList . List.map f . S.toCharListSub   where-    f x = if Case.isCase (Case.opposite (theCase @letterCase)) x-          then ASCII.Substitute-          else x+    f x =+      if Case.isCase (Case.opposite (theCase @letterCase)) x+        then ASCII.Substitute+        else x -{-| Given a string from a larger set that is known to consist entirely of ASCII-    characters in a particular case, map over the characters in the string as if-    they were caseless ASCII characters -}-mapChars :: forall letterCase superset. KnownCase letterCase => StringSuperset superset =>-    (CaselessChar -> CaselessChar) -- ^ Case-insensitive function over ASCII characters-    -> ASCII'case letterCase superset -- ^ String that is known to be valid ASCII in a particular case-    -> ASCII'case letterCase superset+-- | Given a string from a larger set that is known to consist entirely of ASCII+--    characters in a particular case, map over the characters in the string as if+--    they were caseless ASCII characters+mapChars ::+  forall letterCase superset.+  KnownCase letterCase =>+  StringSuperset superset =>+  -- | Case-insensitive function over ASCII characters+  (CaselessChar -> CaselessChar) ->+  -- | String that is known to be valid ASCII in a particular case+  ASCII'case letterCase superset ->+  ASCII'case letterCase superset mapChars f = asciiCaseUnsafe . S.mapCharsUnsafe g . lift   where     g = Caseless.toCase (theCase @letterCase) . f . Caseless.assumeCaseUnsafe (theCase @letterCase) -{-| Given an ASCII superset string that is known to be valid ASCII,-refine it further by converting it to a particular letter case -}-refineStringToCase :: forall letterCase char. KnownCase letterCase => StringSuperset char =>-    ASCII char -> ASCII'case letterCase char+-- | Given an ASCII superset string that is known to be valid ASCII,+-- refine it further by converting it to a particular letter case+refineStringToCase ::+  forall letterCase char.+  KnownCase letterCase =>+  StringSuperset char =>+  ASCII char ->+  ASCII'case letterCase char refineStringToCase = asciiCaseUnsafe . S.toCaseString (theCase @letterCase) . Refinement.lift
library/ASCII/Isomorphism.hs view
@@ -3,22 +3,23 @@ import ASCII.Char (Char) import ASCII.Superset (CharSuperset, StringSuperset, fromChar) import Data.Function (id, (.))+import Data.Kind (Type) import Data.List (map) -class CharSuperset char => CharIso char where-    toChar :: char -> Char+class CharSuperset (char :: Type) => CharIso char where+  toChar :: char -> Char  asChar :: CharIso char => (Char -> Char) -> char -> char asChar f = fromChar . f . toChar -class StringSuperset string => StringIso string where-    toCharList :: string -> [Char]-    mapChars :: (Char -> Char) -> string -> string+class StringSuperset string => StringIso (string :: Type) where+  toCharList :: string -> [Char]+  mapChars :: (Char -> Char) -> string -> string  -- | 'Char' is trivially isomorphic to itself. (This instance is uninteresting.) instance CharIso Char where-    toChar = id+  toChar = id  instance CharIso char => StringIso [char] where-    toCharList = map toChar-    mapChars f = map (asChar f)+  toCharList = map toChar+  mapChars f = map (asChar f)
library/ASCII/Refinement.hs view
@@ -1,9 +1,23 @@ module ASCII.Refinement-  (-    {- * ASCII type constructor -} ASCII, lift, asciiUnsafe,-    {- * Character functions -} validateChar, fromChar, toChar, substituteChar, asChar,-    {- * String functions -} validateString, fromCharList, toCharList, substituteString, mapChars,+  ( -- * ASCII type constructor+    ASCII,+    lift,+    asciiUnsafe,++    -- * Character functions+    validateChar,+    fromChar,+    toChar,+    substituteChar,+    asChar,++    -- * String functions+    validateString,+    fromCharList,+    toCharList,+    substituteString,+    mapChars,   )-  where+where  import ASCII.Refinement.Internal
library/ASCII/Refinement/Internal.hs view
@@ -1,36 +1,35 @@ module ASCII.Refinement.Internal where -import qualified ASCII.Char as ASCII-import qualified ASCII.Isomorphism as I-import qualified ASCII.Superset as S--import {-# source #-} ASCII.SupersetConversion (StringSupersetConversion)+import ASCII.Char qualified as ASCII+import ASCII.Isomorphism qualified as I+import ASCII.Superset qualified as S+import {-# SOURCE #-} ASCII.SupersetConversion (StringSupersetConversion)+import {-# SOURCE #-} ASCII.SupersetConversion qualified as SupersetConversion+import Data.Bool qualified as Bool import Data.Data (Data) import Data.Eq (Eq) import Data.Function (id, ($), (.)) import Data.Hashable (Hashable)+import Data.Kind (Type) import Data.List (map) import Data.Maybe (Maybe (..)) import Data.Monoid (Monoid) import Data.Ord (Ord, (>)) import Data.Semigroup (Semigroup) import GHC.Generics (Generic)+import Text.Show qualified as Show import Prelude (succ) -import qualified Data.Bool as Bool-import qualified Text.Show as Show-import {-# source #-} qualified ASCII.SupersetConversion as SupersetConversion--{-| 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'.--For example, whereas a 'Data.Text.Text' value may contain a combination of ASCII-and non-ASCII characters, a value of type @'ASCII' 'Data.Text.Text'@ may contain-only ASCII characters. -}-newtype ASCII superset = ASCII_Unsafe { lift :: superset }+-- | 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'.+--+-- For example, whereas a 'Data.Text.Text' value may contain a combination of ASCII+-- and non-ASCII characters, a value of type @'ASCII' 'Data.Text.Text'@ may contain+-- only ASCII characters.+newtype ASCII (superset :: Type) = ASCII_Unsafe {lift :: superset}  deriving stock instance Eq superset => Eq (ASCII superset) @@ -47,63 +46,65 @@ deriving stock instance Generic (ASCII superset)  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+  showsPrec d x =+    Show.showParen (d > app_prec) $+      Show.showString "asciiUnsafe " . Show.showsPrec (succ app_prec) (lift x)+    where+      app_prec = 10 -    showList x = Show.showString "asciiUnsafe " . Show.showList (map lift x)+  showList x = Show.showString "asciiUnsafe " . Show.showList (map lift x)  instance S.ToCaselessChar char => S.ToCaselessChar (ASCII char) where-    isAsciiCaselessChar _ = Bool.True-    toCaselessCharUnsafe = S.toCaselessCharUnsafe . lift+  isAsciiCaselessChar _ = Bool.True+  toCaselessCharUnsafe = S.toCaselessCharUnsafe . lift  instance S.CharSuperset char => S.ToChar (ASCII char) where-    isAsciiChar _ = Bool.True-    toCharUnsafe = S.toCharUnsafe . lift+  isAsciiChar _ = Bool.True+  toCharUnsafe = S.toCharUnsafe . lift  instance S.CharSuperset char => S.FromChar (ASCII char) where-    fromChar = asciiUnsafe . S.fromChar+  fromChar = asciiUnsafe . S.fromChar  instance S.CharSuperset char => S.CharSuperset (ASCII char) where-    toCaseChar c = asciiUnsafe . S.toCaseChar c . lift+  toCaseChar c = asciiUnsafe . S.toCaseChar c . lift  instance S.CharSuperset char => I.CharIso (ASCII char) where-    toChar = S.toCharUnsafe+  toChar = S.toCharUnsafe  instance S.ToCaselessString string => S.ToCaselessString (ASCII string) where-    isAsciiCaselessString _ = Bool.True-    toCaselessCharListUnsafe = S.toCaselessCharListUnsafe . lift-    toCaselessCharListSub = S.toCaselessCharListSub . lift+  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+  isAsciiString _ = Bool.True+  toCharListUnsafe = S.toCharListUnsafe . lift+  toCharListSub = S.toCharListUnsafe . lift  instance S.FromString string => S.FromString (ASCII string) where-    fromCharList = asciiUnsafe . S.fromCharList+  fromCharList = asciiUnsafe . S.fromCharList  instance S.StringSuperset string => S.StringSuperset (ASCII string) where-    substituteString = id-    toCaseString c = asciiUnsafe . S.toCaseString c . lift+  substituteString = id+  toCaseString c = asciiUnsafe . S.toCaseString c . lift  instance S.StringSuperset string => I.StringIso (ASCII string) where-    toCharList = S.toCharListUnsafe-    mapChars = S.mapCharsUnsafe--{-| Change the type of an ASCII superset value that is known to be valid ASCII+  toCharList = S.toCharListUnsafe+  mapChars = S.mapCharsUnsafe -This is "unsafe" because this assertion is unchecked, so this function is capable-of producing an invalid 'ASCII' value. -}+-- | Change the type of an ASCII superset value that is known to be valid ASCII+--+-- This is "unsafe" because this assertion is unchecked, so this function is capable+-- of producing an invalid 'ASCII' value. asciiUnsafe :: superset -> ASCII superset asciiUnsafe = ASCII_Unsafe -{-|--@-(map validateChar [-1, 65, 97, 128] :: [Maybe (ASCII Int)])-    == [Nothing, Just (asciiUnsafe 65), Just (asciiUnsafe 97), Nothing]-@ -}+-- |+--+-- @+-- (map validateChar [-1, 65, 97, 128] :: [Maybe (ASCII Int)])+--     == [Nothing, Just (asciiUnsafe 65), Just (asciiUnsafe 97), Nothing]+-- @ validateChar :: S.CharSuperset superset => superset -> Maybe (ASCII superset) validateChar x = if S.isAsciiChar x then Just (asciiUnsafe x) else Nothing @@ -116,42 +117,42 @@ toChar :: S.CharSuperset superset => ASCII superset -> ASCII.Char toChar = S.toCharUnsafe . lift -{-|--@-fromCharList [CapitalLetterH, SmallLetterI, ExclamationMark]-    == (asciiUnsafe "Hi!" :: ASCII Text)-@ -}+-- |+--+-- @+-- fromCharList [CapitalLetterH, SmallLetterI, ExclamationMark]+--     == (asciiUnsafe "Hi!" :: ASCII Text)+-- @ 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 (substituteString \"Piñata" :: ASCII Text) ==+--     [CapitalLetterP, SmallLetterI, Substitute, SmallLetterA, SmallLetterT, SmallLetterA]+-- @ 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-    'ASCII.Substitute' character in place of any non-ASCII characters--@-(substituteString \"Cristóbal" :: ASCII Text) == asciiUnsafe "Crist\SUBbal"-@ -}+-- | Forces a string from a larger character set into ASCII by using the+--    'ASCII.Substitute' character in place of any non-ASCII characters+--+-- @+-- (substituteString \"Cristóbal" :: ASCII Text) == asciiUnsafe "Crist\SUBbal"+-- @ substituteString :: S.StringSuperset superset => superset -> ASCII superset substituteString = asciiUnsafe . S.substituteString -{-|--@-(map validateString [\"Hello", \"Cristóbal"] :: [Maybe (ASCII Text)])-    == [Just (asciiUnsafe \"Hello"), Nothing]--(map validateString [\"Hello", \"Cristóbal"] :: [Maybe (ASCII String)])-    == [Just (asciiUnsafe \"Hello"), Nothing]-@ -}+-- |+--+-- @+-- (map validateString [\"Hello", \"Cristóbal"] :: [Maybe (ASCII Text)])+--     == [Just (asciiUnsafe \"Hello"), Nothing]+--+-- (map validateString [\"Hello", \"Cristóbal"] :: [Maybe (ASCII String)])+--     == [Just (asciiUnsafe \"Hello"), Nothing]+-- @ validateString :: S.StringSuperset superset => superset -> Maybe (ASCII superset) validateString x = if S.isAsciiString x then Just (asciiUnsafe x) else Nothing @@ -161,6 +162,6 @@ mapChars :: S.StringSuperset superset => (ASCII.Char -> ASCII.Char) -> ASCII superset -> ASCII superset mapChars f = asciiUnsafe . S.mapCharsUnsafe f . lift -{-| For example, this function can convert @ASCII ByteString@ to @ASCII Text@ and vice versa -}+-- | For example, this function can convert @ASCII ByteString@ to @ASCII Text@ and vice versa convertRefinedString :: StringSupersetConversion a b => ASCII a -> ASCII b convertRefinedString (ASCII_Unsafe x) = ASCII_Unsafe (SupersetConversion.convertStringUnsafe x)
library/ASCII/Refinement/Internal.hs-boot view
@@ -1,11 +1,13 @@ module ASCII.Refinement.Internal where  import {-# source #-} ASCII.SupersetConversion (StringSupersetConversion)+import Data.Kind (Type) -data ASCII superset+data ASCII (superset :: Type) -lift :: ASCII superset -> superset+lift :: forall (superset :: Type). ASCII superset -> superset -asciiUnsafe :: superset -> ASCII superset+asciiUnsafe :: forall (superset :: Type). superset -> ASCII superset -convertRefinedString :: StringSupersetConversion a b => ASCII a -> ASCII b+convertRefinedString :: StringSupersetConversion (a :: Type) (b :: Type) =>+  ASCII a -> ASCII b
library/ASCII/Superset.hs view
@@ -1,112 +1,132 @@ module ASCII.Superset-  (-    {- * Characters -}-    {- ** Class -} ToCaselessChar (..), ToChar (..), FromChar (..), CharSuperset (..), ToCasefulChar (..),-    {- ** Functions -} asCharUnsafe, toCharMaybe, toCaselessCharMaybe, toCharOrFail, toCaselessCharOrFail,-        toCharSub, toCaselessCharSub, substituteChar, convertCharMaybe, convertCharOrFail,+  ( -- * Characters -    {- * Strings -}-    {- ** Class -} ToCaselessString (..), ToString (..), FromString (..), StringSuperset (..), ToCasefulString (..),-    {- ** Functions -} toCharListMaybe, toCaselessCharListMaybe, toCharListOrFail, toCaselessCharListOrFail,-        convertStringMaybe, convertStringOrFail+    -- ** Class+    ToCaselessChar (..),+    ToChar (..),+    FromChar (..),+    CharSuperset (..),+    ToCasefulChar (..),++    -- ** Functions+    asCharUnsafe,+    toCharMaybe,+    toCaselessCharMaybe,+    toCharOrFail,+    toCaselessCharOrFail,+    toCharSub,+    toCaselessCharSub,+    substituteChar,+    convertCharMaybe,+    convertCharOrFail,++    -- * Strings++    -- ** Class+    ToCaselessString (..),+    ToString (..),+    FromString (..),+    StringSuperset (..),+    ToCasefulString (..),++    -- ** Functions+    toCharListMaybe,+    toCaselessCharListMaybe,+    toCharListOrFail,+    toCaselessCharListOrFail,+    convertStringMaybe,+    convertStringOrFail,   )-  where+where  import ASCII.Case (Case (..))+import ASCII.Case qualified as Case+import {-# SOURCE #-} ASCII.CaseRefinement (KnownCase (..)) import ASCII.Caseless (CaselessChar)-import {-# source #-} ASCII.CaseRefinement (KnownCase (..))+import ASCII.Caseless qualified as Caseless+import ASCII.Char qualified as ASCII import Control.Monad (return) import Control.Monad.Fail (MonadFail (fail)) import Data.Bool (Bool, (&&))+import Data.Bool qualified as Bool+import Data.ByteString qualified as BS+import Data.ByteString.Builder qualified as BSB+import Data.ByteString.Lazy qualified as LBS+import Data.Char qualified as Unicode import Data.Function (id, (.)) import Data.Functor (fmap)+import Data.Int qualified as Int+import Data.Kind (Type)+import Data.List qualified as List import Data.Maybe (Maybe (..)) import Data.Ord ((<=), (>=))+import Data.Text qualified as T+import Data.Text.Lazy qualified as LT+import Data.Text.Lazy.Builder qualified as TB+import Data.Word qualified as Word+import Numeric.Natural qualified as Nat import Prelude ((+), (-))--import qualified ASCII.Case as Case-import qualified ASCII.Caseless as Caseless-import qualified ASCII.Char as ASCII-import qualified Data.Bool as Bool-import qualified Data.ByteString as BS-import qualified Data.ByteString.Builder as BSB-import qualified Data.ByteString.Lazy as LBS-import qualified Data.Char as Unicode-import qualified Data.Int as Int-import qualified Data.List as List-import qualified Data.Text as T-import qualified Data.Text.Lazy as LT-import qualified Data.Text.Lazy.Builder as TB-import qualified Data.Word as Word-import qualified Numeric.Natural as Nat-import qualified Prelude-+import Prelude qualified  ---  Char  --- -{-| 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.--This does /not/ include 'CaselessChar', because that cannot be converted to-'ASCII.Char' without choosing a case. -}-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.--This does /not/ include 'ASCII.CaseRefinement.ASCII'case', because that represents-a subset of 'ASCII.Char'; not all characters are of the wanted case, so no total-conversion is possible without changing case. -}-class FromChar char where--    -- | Conversion from 'ASCII.Char'-    fromChar :: ASCII.Char -> char+-- | 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 :: Type) where+  -- | Test whether a character can be converted to 'CaselessChar'+  isAsciiCaselessChar :: char -> Bool -{- | Character type with:+  -- | Conversion to 'CaselessChar', defined only where 'isAsciiCaselessChar' is satisfied+  toCaselessCharUnsafe :: char -> CaselessChar -- a total conversion from ASCII; and-- a partial conversion to ASCII -}-class (ToChar char, FromChar char) => CharSuperset char where+-- | 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.+--+-- This does /not/ include 'CaselessChar', because that cannot be converted to+-- 'ASCII.Char' without choosing a case.+class ToCaselessChar char => ToChar (char :: Type) where+  -- | Test whether a character can be converted to 'ASCII.Char'+  isAsciiChar :: char -> Bool -    {- | Convert a character in the superset to the designated case,-    if it is an ASCII letter of the opposite case. Otherwise, return-    the argument unmodified. -}-    toCaseChar :: Case -> char -> char+  -- | Conversion to 'ASCII.Char', defined only where 'isAsciiChar' is satisfied+  toCharUnsafe :: char -> ASCII.Char -class ToCasefulChar (letterCase :: Case) char where+-- | 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.+--+-- This does /not/ include 'ASCII.CaseRefinement.ASCII'case', because that represents+-- a subset of 'ASCII.Char'; not all characters are of the wanted case, so no total+-- conversion is possible without changing case.+class FromChar (char :: Type) where+  -- | Conversion from 'ASCII.Char'+  fromChar :: ASCII.Char -> char -    toCasefulChar :: CaselessChar -> char+-- | Character type with:+--+-- - a total conversion from ASCII; and+-- - a partial conversion to ASCII+class (ToChar char, FromChar char) => CharSuperset (char :: Type) where+  -- | Convert a character in the superset to the designated case,+  --    if it is an ASCII letter of the opposite case. Otherwise, return+  --    the argument unmodified.+  toCaseChar :: Case -> char -> char -{-| Manipulate a character as if it were an ASCII 'ASCII.Char', assuming that it is+class ToCasefulChar (letterCase :: Case) (char :: Type) where+  toCasefulChar :: CaselessChar -> char -Defined only where 'isAsciiChar' is satisfied. -}+-- | 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 @@ -117,11 +137,15 @@ toCaselessCharMaybe = toCaselessCharOrFail  toCharOrFail :: (ToChar char, MonadFail context) => char -> context ASCII.Char-toCharOrFail x = if isAsciiChar x then return (toCharUnsafe x)+toCharOrFail x =+  if isAsciiChar x+    then return (toCharUnsafe x)     else fail "Not an ASCII character"  toCaselessCharOrFail :: (ToCaselessChar char, MonadFail context) => char -> context CaselessChar-toCaselessCharOrFail x = if isAsciiCaselessChar x then return (toCaselessCharUnsafe x)+toCaselessCharOrFail x =+  if isAsciiCaselessChar x+    then return (toCaselessCharUnsafe x)     else fail "Not an ASCII character"  toCharSub :: ToChar char => char -> ASCII.Char@@ -130,105 +154,101 @@ 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'. -}+-- | 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. -}+-- | 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 :: (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 :: (ToChar char1, FromChar char2, MonadFail context) =>-    char1 -> context char2+-- | 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 ::+  (ToChar char1, FromChar char2, MonadFail context) =>+  char1 ->+  context char2 convertCharOrFail = fmap fromChar . toCharOrFail - ---  String  --- -{-| Partial conversion to @['CaselessChar']@--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--    -- | 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.--This does /not/ include @['CaselessChar']@, because that cannot be converted-to @['ASCII.Char']@ without choosing a case. -}-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.+-- | Partial conversion to @['CaselessChar']@+--+-- 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 :: Type) where+  -- | Test whether a character can be converted to @['CaselessChar']@+  isAsciiCaselessString :: string -> Bool -This does /not/ include @['ASCII.CaseRefinement.ASCII'case']@, because that-represents a subset of ASCII; not all ASCII characters are of case wanted by-'ASCII.CaseRefinement.ASCII'case', so no total conversion is possible without-changing case. -}-class FromString string where+  -- | Conversion to @['CaselessChar']@, defined only where+  --        'isAsciiCaselessString' is satisfied+  toCaselessCharListUnsafe :: string -> [CaselessChar] -    -- | Conversion from @['ASCII.Char']@-    fromCharList :: [ASCII.Char] -> string+  -- | Conversion to @['CaselessChar']@ achieved by using+  --        'Caseless.Substitute' in place of any non-ASCII characters+  toCaselessCharListSub :: string -> [CaselessChar] -{- | String type with:+-- | 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.+--+-- This does /not/ include @['CaselessChar']@, because that cannot be converted+-- to @['ASCII.Char']@ without choosing a case.+class ToCaselessString string => ToString (string :: Type) where+  -- | Test whether a string can be converted to @['ASCII.Char']@+  isAsciiString :: string -> Bool -- a total conversion from ASCII; and-- a partial conversion to ASCII -}-class (ToString string, FromString string) => StringSuperset string where+  -- | Conversion to @['ASCII.Char']@, defined only where 'isAsciiString'+  --        is satisfied+  toCharListUnsafe :: string -> [ASCII.Char] -    {-| Force a string into ASCII by replacing any non-ASCII character with 'ASCII.Substitute'+  -- | Conversion to @['ASCII.Char']@ achieved by using+  --        'ASCII.Substitute' in place of any non-ASCII characters+  toCharListSub :: string -> [ASCII.Char] -        The resulting string satisfies 'isAsciiString' and 'isAsciiCaselessString'. -}-    substituteString :: string -> string+-- | 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.+--+-- This does /not/ include @['ASCII.CaseRefinement.ASCII'case']@, because that+-- represents a subset of ASCII; not all ASCII characters are of case wanted by+-- 'ASCII.CaseRefinement.ASCII'case', so no total conversion is possible without+-- changing case.+class FromString (string :: Type) where+  -- | Conversion from @['ASCII.Char']@+  fromCharList :: [ASCII.Char] -> string -    mapCharsUnsafe :: (ASCII.Char -> ASCII.Char) -> string -> string-    mapCharsUnsafe f = fromCharList  . List.map f . toCharListUnsafe+-- | String type with:+--+-- - a total conversion from ASCII; and+-- - a partial conversion to ASCII+class (ToString string, FromString string) => StringSuperset (string :: Type) 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 -    {- | Convert each character in the superset to the designated case, if it is-    an ASCII letter of the opposite case. Leaves other characters unchanged. -}-    toCaseString :: Case -> string -> string+  mapCharsUnsafe :: (ASCII.Char -> ASCII.Char) -> string -> string+  mapCharsUnsafe f = fromCharList . List.map f . toCharListUnsafe -class ToCasefulString (letterCase :: Case) string where+  -- | Convert each character in the superset to the designated case, if it is+  --    an ASCII letter of the opposite case. Leaves other characters unchanged.+  toCaseString :: Case -> string -> string -    toCasefulString :: [CaselessChar] -> string+class ToCasefulString (letterCase :: Case) (string :: Type) where+  toCasefulString :: [CaselessChar] -> string  toCharListMaybe :: ToString string => string -> Maybe [ASCII.Char] toCharListMaybe = toCharListOrFail@@ -236,303 +256,314 @@ 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)+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)+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 :: (ToString string1, FromString string2) =>-    string1 -> Maybe string2+-- | 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 ::+  (ToString string1, FromString string2) =>+  string1 ->+  Maybe string2 convertStringMaybe = convertStringOrFail -{-| 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 with 'fail' if the input-contains any character that is outside the ASCII character set. -}-convertStringOrFail :: (ToString string1, FromString string2, MonadFail context) =>-    string1 -> context string2+-- | 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 with 'fail' if the input+-- contains any character that is outside the ASCII character set.+convertStringOrFail ::+  (ToString string1, FromString string2, MonadFail context) =>+  string1 ->+  context string2 convertStringOrFail = fmap fromCharList . toCharListOrFail - ---  Instances  ---  -- | 'CaselessChar' is trivially convertible to itself. instance ToCaselessChar CaselessChar where-    isAsciiCaselessChar _ = Bool.True-    toCaselessCharUnsafe = id+  isAsciiCaselessChar _ = Bool.True+  toCaselessCharUnsafe = id  instance FromChar CaselessChar where-    fromChar = Caseless.disregardCase+  fromChar = Caseless.disregardCase  ---  instance ToCaselessChar ASCII.Char where-    isAsciiCaselessChar _ = Bool.True-    toCaselessCharUnsafe = Caseless.disregardCase+  isAsciiCaselessChar _ = Bool.True+  toCaselessCharUnsafe = Caseless.disregardCase  instance ToChar ASCII.Char where-    isAsciiChar _ = Bool.True-    toCharUnsafe = id+  isAsciiChar _ = Bool.True+  toCharUnsafe = id  instance FromChar ASCII.Char where-    fromChar = id+  fromChar = id  -- | 'ASCII.Char' is trivially a superset of itself. instance CharSuperset ASCII.Char where-    toCaseChar = Case.toCase+  toCaseChar = Case.toCase  instance KnownCase letterCase => ToCasefulChar letterCase ASCII.Char where-    toCasefulChar = Caseless.toCase (theCase @letterCase)+  toCasefulChar = Caseless.toCase (theCase @letterCase)  ---  instance ToCaselessChar Unicode.Char where-    isAsciiCaselessChar = isAsciiChar-    toCaselessCharUnsafe = toCaselessCharUnsafe . toCharUnsafe+  isAsciiCaselessChar = isAsciiChar+  toCaselessCharUnsafe = toCaselessCharUnsafe . toCharUnsafe  instance ToChar Unicode.Char where-    isAsciiChar = (<= '\DEL')-    toCharUnsafe = toCharUnsafe @Int.Int . Unicode.ord+  isAsciiChar = (<= '\DEL')+  toCharUnsafe = toCharUnsafe @Int.Int . Unicode.ord  instance FromChar Unicode.Char where-    fromChar = Unicode.chr . ASCII.toInt+  fromChar = Unicode.chr . ASCII.toInt  instance CharSuperset Unicode.Char where-    toCaseChar UpperCase x | x >= 'a' && x <= 'z' = Unicode.chr (Unicode.ord x - 32)-    toCaseChar LowerCase x | x >= 'A' && x <= 'Z' = Unicode.chr (Unicode.ord x + 32)-    toCaseChar _ x = x+  toCaseChar UpperCase x | x >= 'a' && x <= 'z' = Unicode.chr (Unicode.ord x - 32)+  toCaseChar LowerCase x | x >= 'A' && x <= 'Z' = Unicode.chr (Unicode.ord x + 32)+  toCaseChar _ x = x  instance KnownCase letterCase => ToCasefulChar letterCase Unicode.Char where-    toCasefulChar = fromChar . toCasefulChar @letterCase+  toCasefulChar = fromChar . toCasefulChar @letterCase  ---  instance ToCaselessChar Nat.Natural where-    isAsciiCaselessChar = isAsciiChar-    toCaselessCharUnsafe = toCaselessCharUnsafe . toCharUnsafe+  isAsciiCaselessChar = isAsciiChar+  toCaselessCharUnsafe = toCaselessCharUnsafe . toCharUnsafe  instance ToChar Nat.Natural where-    isAsciiChar = (<= 127)-    toCharUnsafe = toCharUnsafe @Int.Int . Prelude.fromIntegral+  isAsciiChar = (<= 127)+  toCharUnsafe = toCharUnsafe @Int.Int . Prelude.fromIntegral  instance FromChar Nat.Natural where-    fromChar = Prelude.fromIntegral . ASCII.toInt+  fromChar = Prelude.fromIntegral . ASCII.toInt  instance CharSuperset Nat.Natural where-    toCaseChar UpperCase x | x >= 97 && x <= 122 = x - 32-    toCaseChar LowerCase x | x >= 65 && x <= 90  = x + 32-    toCaseChar _ x = x+  toCaseChar UpperCase x | x >= 97 && x <= 122 = x - 32+  toCaseChar LowerCase x | x >= 65 && x <= 90 = x + 32+  toCaseChar _ x = x  instance KnownCase letterCase => ToCasefulChar letterCase Nat.Natural where-    toCasefulChar = fromChar . toCasefulChar @letterCase+  toCasefulChar = fromChar . toCasefulChar @letterCase  ---  instance ToCaselessChar Int.Int where-    isAsciiCaselessChar = isAsciiChar-    toCaselessCharUnsafe = toCaselessCharUnsafe . toCharUnsafe+  isAsciiCaselessChar = isAsciiChar+  toCaselessCharUnsafe = toCaselessCharUnsafe . toCharUnsafe  instance ToChar Int.Int where-    isAsciiChar x = (x >= 0) && (x <= 127)-    toCharUnsafe = ASCII.fromIntUnsafe+  isAsciiChar x = (x >= 0) && (x <= 127)+  toCharUnsafe = ASCII.fromIntUnsafe  instance FromChar Int.Int where-    fromChar = ASCII.toInt+  fromChar = ASCII.toInt  instance CharSuperset Int.Int where-    toCaseChar UpperCase x | x >= 97 && x <= 122 = x - 32-    toCaseChar LowerCase x | x >= 65 && x <= 90  = x + 32-    toCaseChar _ x = x+  toCaseChar UpperCase x | x >= 97 && x <= 122 = x - 32+  toCaseChar LowerCase x | x >= 65 && x <= 90 = x + 32+  toCaseChar _ x = x  instance KnownCase letterCase => ToCasefulChar letterCase Int.Int where-    toCasefulChar = fromChar . toCasefulChar @letterCase+  toCasefulChar = fromChar . toCasefulChar @letterCase  ---  instance ToCaselessChar Word.Word8 where-    isAsciiCaselessChar = isAsciiChar-    toCaselessCharUnsafe = toCaselessCharUnsafe . toCharUnsafe+  isAsciiCaselessChar = isAsciiChar+  toCaselessCharUnsafe = toCaselessCharUnsafe . toCharUnsafe  instance ToChar Word.Word8 where-    isAsciiChar = (<= 127)-    toCharUnsafe = ASCII.fromIntUnsafe . Prelude.fromIntegral+  isAsciiChar = (<= 127)+  toCharUnsafe = ASCII.fromIntUnsafe . Prelude.fromIntegral  instance FromChar Word.Word8 where-    fromChar = Prelude.fromIntegral . ASCII.toInt+  fromChar = Prelude.fromIntegral . ASCII.toInt  instance CharSuperset Word.Word8 where-    toCaseChar UpperCase x | x >= 97 && x <= 122 = x - 32-    toCaseChar LowerCase x | x >= 65 && x <= 90  = x + 32-    toCaseChar _ x = x+  toCaseChar UpperCase x | x >= 97 && x <= 122 = x - 32+  toCaseChar LowerCase x | x >= 65 && x <= 90 = x + 32+  toCaseChar _ x = x  instance KnownCase letterCase => ToCasefulChar letterCase Word.Word8 where-    toCasefulChar = fromChar . toCasefulChar @letterCase+  toCasefulChar = fromChar . toCasefulChar @letterCase  ---  instance ToCaselessChar char => ToCaselessString [char] where-    isAsciiCaselessString    = List.all isAsciiCaselessChar-    toCaselessCharListUnsafe = List.map toCaselessCharUnsafe-    toCaselessCharListSub    = List.map toCaselessCharSub+  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+  isAsciiString = List.all isAsciiChar+  toCharListUnsafe = List.map toCharUnsafe+  toCharListSub = List.map toCharSub  instance FromChar char => FromString [char] where-    fromCharList = List.map fromChar+  fromCharList = List.map fromChar  instance CharSuperset char => StringSuperset [char] where-    substituteString = List.map substituteChar-    toCaseString c = List.map (toCaseChar c)+  substituteString = List.map substituteChar+  toCaseString c = List.map (toCaseChar c)  instance (ToCasefulChar letterCase char, KnownCase letterCase) => ToCasefulString letterCase [char] where-    toCasefulString = List.map (toCasefulChar @letterCase)+  toCasefulString = List.map (toCasefulChar @letterCase)  ---  instance ToCaselessString T.Text where-    isAsciiCaselessString = T.all isAsciiChar-    toCaselessCharListUnsafe = toCaselessCharListUnsafe . T.unpack-    toCaselessCharListSub    = toCaselessCharListSub    . T.unpack+  isAsciiCaselessString = T.all isAsciiChar+  toCaselessCharListUnsafe = toCaselessCharListUnsafe . T.unpack+  toCaselessCharListSub = toCaselessCharListSub . T.unpack  instance ToString T.Text where-    isAsciiString = T.all isAsciiChar-    toCharListUnsafe = toCharListUnsafe . T.unpack-    toCharListSub = toCharListSub . T.unpack+  isAsciiString = T.all isAsciiChar+  toCharListUnsafe = toCharListUnsafe . T.unpack+  toCharListSub = toCharListSub . T.unpack  instance FromString T.Text where-    fromCharList = T.pack . fromCharList+  fromCharList = T.pack . fromCharList  instance StringSuperset T.Text where-    substituteString = T.map substituteChar-    mapCharsUnsafe f = T.map (asCharUnsafe f)-    toCaseString c   = T.map (toCaseChar c)+  substituteString = T.map substituteChar+  mapCharsUnsafe f = T.map (asCharUnsafe f)+  toCaseString c = T.map (toCaseChar c)  instance KnownCase letterCase => ToCasefulString letterCase T.Text where-    toCasefulString = fromCharList . toCasefulString @letterCase+  toCasefulString = fromCharList . toCasefulString @letterCase  ---  instance ToCaselessString LT.Text where-    isAsciiCaselessString = LT.all isAsciiChar-    toCaselessCharListUnsafe = toCaselessCharListUnsafe . LT.unpack-    toCaselessCharListSub    = toCaselessCharListSub    . LT.unpack+  isAsciiCaselessString = LT.all isAsciiChar+  toCaselessCharListUnsafe = toCaselessCharListUnsafe . LT.unpack+  toCaselessCharListSub = toCaselessCharListSub . LT.unpack  instance ToString LT.Text where-    isAsciiString = LT.all isAsciiChar-    toCharListUnsafe = toCharListUnsafe . LT.unpack-    toCharListSub    = toCharListSub    . LT.unpack+  isAsciiString = LT.all isAsciiChar+  toCharListUnsafe = toCharListUnsafe . LT.unpack+  toCharListSub = toCharListSub . LT.unpack  instance FromString LT.Text where-    fromCharList = LT.pack . fromCharList+  fromCharList = LT.pack . fromCharList  instance StringSuperset LT.Text where-    substituteString = LT.map substituteChar-    mapCharsUnsafe f = LT.map (asCharUnsafe f)-    toCaseString c   = LT.map (toCaseChar c)+  substituteString = LT.map substituteChar+  mapCharsUnsafe f = LT.map (asCharUnsafe f)+  toCaseString c = LT.map (toCaseChar c)  instance KnownCase letterCase => ToCasefulString letterCase LT.Text where-    toCasefulString = fromCharList . toCasefulString @letterCase+  toCasefulString = fromCharList . toCasefulString @letterCase  ---  instance ToCaselessString TB.Builder where-    isAsciiCaselessString    = isAsciiCaselessString    . TB.toLazyText-    toCaselessCharListUnsafe = toCaselessCharListUnsafe . TB.toLazyText-    toCaselessCharListSub    = toCaselessCharListSub    . TB.toLazyText+  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+  isAsciiString = isAsciiString . TB.toLazyText+  toCharListUnsafe = toCharListUnsafe . TB.toLazyText+  toCharListSub = toCharListSub . TB.toLazyText  instance FromString TB.Builder where-    fromCharList = TB.fromString . fromCharList+  fromCharList = TB.fromString . fromCharList  instance StringSuperset TB.Builder where-    substituteString = TB.fromLazyText . substituteString . TB.toLazyText-    mapCharsUnsafe f = TB.fromLazyText . mapCharsUnsafe f . TB.toLazyText-    toCaseString c   = TB.fromLazyText . toCaseString c   . TB.toLazyText+  substituteString = TB.fromLazyText . substituteString . TB.toLazyText+  mapCharsUnsafe f = TB.fromLazyText . mapCharsUnsafe f . TB.toLazyText+  toCaseString c = TB.fromLazyText . toCaseString c . TB.toLazyText  instance KnownCase letterCase => ToCasefulString letterCase TB.Builder where-    toCasefulString = fromCharList . toCasefulString @letterCase+  toCasefulString = fromCharList . toCasefulString @letterCase  ---  instance ToCaselessString BS.ByteString where-    isAsciiCaselessString = BS.all isAsciiCaselessChar-    toCaselessCharListUnsafe = toCaselessCharListUnsafe . BS.unpack-    toCaselessCharListSub    = toCaselessCharListSub    . BS.unpack+  isAsciiCaselessString = BS.all isAsciiCaselessChar+  toCaselessCharListUnsafe = toCaselessCharListUnsafe . BS.unpack+  toCaselessCharListSub = toCaselessCharListSub . BS.unpack  instance ToString BS.ByteString where-    isAsciiString = BS.all isAsciiChar-    toCharListUnsafe = toCharListUnsafe . BS.unpack-    toCharListSub    = toCharListSub    . BS.unpack+  isAsciiString = BS.all isAsciiChar+  toCharListUnsafe = toCharListUnsafe . BS.unpack+  toCharListSub = toCharListSub . BS.unpack  instance FromString BS.ByteString where-    fromCharList = BS.pack . fromCharList+  fromCharList = BS.pack . fromCharList  instance StringSuperset BS.ByteString where-    substituteString = BS.map substituteChar-    mapCharsUnsafe f = BS.map (asCharUnsafe f)-    toCaseString c   = BS.map (toCaseChar c)+  substituteString = BS.map substituteChar+  mapCharsUnsafe f = BS.map (asCharUnsafe f)+  toCaseString c = BS.map (toCaseChar c)  instance KnownCase letterCase => ToCasefulString letterCase BS.ByteString where-    toCasefulString = fromCharList . toCasefulString @letterCase+  toCasefulString = fromCharList . toCasefulString @letterCase  ---  instance ToCaselessString LBS.ByteString where-    isAsciiCaselessString = LBS.all isAsciiCaselessChar-    toCaselessCharListUnsafe = toCaselessCharListUnsafe . LBS.unpack-    toCaselessCharListSub    = toCaselessCharListSub    . LBS.unpack+  isAsciiCaselessString = LBS.all isAsciiCaselessChar+  toCaselessCharListUnsafe = toCaselessCharListUnsafe . LBS.unpack+  toCaselessCharListSub = toCaselessCharListSub . LBS.unpack  instance ToString LBS.ByteString where-    isAsciiString = LBS.all isAsciiChar-    toCharListUnsafe = toCharListUnsafe . LBS.unpack-    toCharListSub    = toCharListSub    . LBS.unpack+  isAsciiString = LBS.all isAsciiChar+  toCharListUnsafe = toCharListUnsafe . LBS.unpack+  toCharListSub = toCharListSub . LBS.unpack  instance FromString LBS.ByteString where-    fromCharList = LBS.pack . fromCharList+  fromCharList = LBS.pack . fromCharList  instance StringSuperset LBS.ByteString where-    substituteString = LBS.map substituteChar-    mapCharsUnsafe f = LBS.map (asCharUnsafe f)-    toCaseString c   = LBS.map (toCaseChar c)+  substituteString = LBS.map substituteChar+  mapCharsUnsafe f = LBS.map (asCharUnsafe f)+  toCaseString c = LBS.map (toCaseChar c)  instance KnownCase letterCase => ToCasefulString letterCase LBS.ByteString where-    toCasefulString = fromCharList . toCasefulString @letterCase+  toCasefulString = fromCharList . toCasefulString @letterCase  ---  instance ToCaselessString BSB.Builder where-    isAsciiCaselessString    = isAsciiCaselessString    . BSB.toLazyByteString-    toCaselessCharListUnsafe = toCaselessCharListUnsafe . BSB.toLazyByteString-    toCaselessCharListSub    = toCaselessCharListSub    . BSB.toLazyByteString+  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+  isAsciiString = isAsciiString . BSB.toLazyByteString+  toCharListUnsafe = toCharListUnsafe . BSB.toLazyByteString+  toCharListSub = toCharListSub . BSB.toLazyByteString  instance FromString BSB.Builder where-    fromCharList = BSB.lazyByteString . fromCharList+  fromCharList = BSB.lazyByteString . fromCharList  instance StringSuperset BSB.Builder where-    substituteString = BSB.lazyByteString . substituteString . BSB.toLazyByteString-    mapCharsUnsafe f = BSB.lazyByteString . mapCharsUnsafe f . BSB.toLazyByteString-    toCaseString c   = BSB.lazyByteString . toCaseString c   . BSB.toLazyByteString+  substituteString = BSB.lazyByteString . substituteString . BSB.toLazyByteString+  mapCharsUnsafe f = BSB.lazyByteString . mapCharsUnsafe f . BSB.toLazyByteString+  toCaseString c = BSB.lazyByteString . toCaseString c . BSB.toLazyByteString  instance KnownCase letterCase => ToCasefulString letterCase BSB.Builder where-    toCasefulString = fromCharList . toCasefulString @letterCase+  toCasefulString = fromCharList . toCasefulString @letterCase
library/ASCII/Superset/Text.hs view
@@ -1,74 +1,74 @@ module ASCII.Superset.Text where  import ASCII.CaseRefinement (ASCII'case)+import ASCII.CaseRefinement qualified as CaseRefinement import ASCII.Refinement (ASCII)+import ASCII.Refinement qualified as Refinement+import Data.ByteString qualified as Strict (ByteString)+import Data.ByteString.Lazy qualified as Lazy (ByteString)+import Data.Char qualified as Unicode import Data.Function (id, (.))--import qualified ASCII.CaseRefinement as CaseRefinement-import qualified ASCII.Refinement as Refinement-import qualified Data.ByteString as Strict (ByteString)-import qualified Data.ByteString.Lazy as Lazy (ByteString)-import qualified Data.Char as Unicode-import qualified Data.Text as Strict (Text)-import qualified Data.Text as Text.Strict-import qualified Data.Text.Encoding as Text.Strict-import qualified Data.Text.Lazy as Lazy (Text)-import qualified Data.Text.Lazy as Text.Lazy-import qualified Data.Text.Lazy.Encoding as Text.Lazy+import Data.Kind (Type)+import Data.Text qualified as Strict (Text)+import Data.Text qualified as Text.Strict+import Data.Text.Encoding qualified as Text.Strict+import Data.Text.Lazy qualified as Lazy (Text)+import Data.Text.Lazy qualified as Text.Lazy+import Data.Text.Lazy.Encoding qualified as Text.Lazy -class ToText a where-    toStrictText :: a -> Strict.Text-    toStrictText = Text.Lazy.toStrict . toLazyText+class ToText (a :: Type) where+  toStrictText :: a -> Strict.Text+  toStrictText = Text.Lazy.toStrict . toLazyText -    toLazyText :: a -> Lazy.Text-    toLazyText = Text.Lazy.fromStrict . toStrictText+  toLazyText :: a -> Lazy.Text+  toLazyText = Text.Lazy.fromStrict . toStrictText -    toUnicodeCharList :: a -> [Unicode.Char]-    toUnicodeCharList = Text.Lazy.unpack . toLazyText+  toUnicodeCharList :: a -> [Unicode.Char]+  toUnicodeCharList = Text.Lazy.unpack . toLazyText -    {-# minimal toStrictText | toLazyText #-}+  {-# MINIMAL toStrictText | toLazyText #-}  instance ToText Strict.Text where-    toStrictText = id+  toStrictText = id  instance ToText Lazy.Text where-    toLazyText = id+  toLazyText = id  instance ToText [Unicode.Char] where-    toUnicodeCharList = id-    toStrictText = Text.Strict.pack-    toLazyText = Text.Lazy.pack+  toUnicodeCharList = id+  toStrictText = Text.Strict.pack+  toLazyText = Text.Lazy.pack  instance ToText (ASCII Strict.Text) where-    toStrictText = Refinement.lift+  toStrictText = Refinement.lift  instance ToText (ASCII Lazy.Text) where-    toLazyText = Refinement.lift+  toLazyText = Refinement.lift  instance ToText (ASCII Strict.ByteString) where-    toStrictText = Text.Strict.decodeUtf8 . Refinement.lift+  toStrictText = Text.Strict.decodeUtf8 . Refinement.lift  instance ToText (ASCII Lazy.ByteString) where-    toLazyText = Text.Lazy.decodeUtf8 . Refinement.lift+  toLazyText = Text.Lazy.decodeUtf8 . Refinement.lift  instance ToText (ASCII [Unicode.Char]) where-    toUnicodeCharList = Refinement.lift-    toStrictText = Text.Strict.pack . Refinement.lift-    toLazyText = Text.Lazy.pack . Refinement.lift+  toUnicodeCharList = Refinement.lift+  toStrictText = Text.Strict.pack . Refinement.lift+  toLazyText = Text.Lazy.pack . Refinement.lift  instance ToText (ASCII'case letterCase Strict.Text) where-    toStrictText = Refinement.lift . CaseRefinement.forgetCase+  toStrictText = Refinement.lift . CaseRefinement.forgetCase  instance ToText (ASCII'case letterCase Lazy.Text) where-    toLazyText = Refinement.lift . CaseRefinement.forgetCase+  toLazyText = Refinement.lift . CaseRefinement.forgetCase  instance ToText (ASCII'case letterCase Strict.ByteString) where-    toStrictText = Text.Strict.decodeUtf8 . Refinement.lift . CaseRefinement.forgetCase+  toStrictText = Text.Strict.decodeUtf8 . Refinement.lift . CaseRefinement.forgetCase  instance ToText (ASCII'case letterCase Lazy.ByteString) where-    toLazyText = Text.Lazy.decodeUtf8 . Refinement.lift . CaseRefinement.forgetCase+  toLazyText = Text.Lazy.decodeUtf8 . Refinement.lift . CaseRefinement.forgetCase  instance ToText (ASCII'case letterCase [Unicode.Char]) where-    toUnicodeCharList = Refinement.lift . CaseRefinement.forgetCase-    toStrictText = Text.Strict.pack . Refinement.lift . CaseRefinement.forgetCase-    toLazyText = Text.Lazy.pack . Refinement.lift . CaseRefinement.forgetCase+  toUnicodeCharList = Refinement.lift . CaseRefinement.forgetCase+  toStrictText = Text.Strict.pack . Refinement.lift . CaseRefinement.forgetCase+  toLazyText = Text.Lazy.pack . Refinement.lift . CaseRefinement.forgetCase
library/ASCII/SupersetConversion.hs view
@@ -1,73 +1,77 @@ module ASCII.SupersetConversion-  (-    {- * Class -} StringSupersetConversion (..),-    {- * Utilities -} convertRefinedString,+  ( -- * Class+    StringSupersetConversion (..),++    -- * Utilities+    convertRefinedString,   )-  where+where +import {-# SOURCE #-} ASCII.Refinement.Internal (convertRefinedString) import ASCII.Superset--import {-# source #-} ASCII.Refinement.Internal (convertRefinedString)--import qualified Data.ByteString as BS-import qualified Data.ByteString.Char8 as BS.Char8-import qualified Data.ByteString.Lazy as LBS-import qualified Data.ByteString.Lazy.Char8 as LBS.Char8-import qualified Data.Char as Unicode-import qualified Data.Text as T-import qualified Data.Text.Encoding as T-import qualified Data.Text.Lazy as LT-import qualified Data.Text.Lazy.Encoding as LT+import Data.ByteString qualified as BS+import Data.ByteString.Char8 qualified as BS.Char8+import Data.ByteString.Lazy qualified as LBS+import Data.ByteString.Lazy.Char8 qualified as LBS.Char8+import Data.Char qualified as Unicode+import Data.Kind (Type)+import Data.Text qualified as T+import Data.Text.Encoding qualified as T+import Data.Text.Lazy qualified as LT+import Data.Text.Lazy.Encoding qualified as LT -class (StringSuperset a, StringSuperset b) => StringSupersetConversion a b where-    convertStringUnsafe :: a -> b+class+  (StringSuperset a, StringSuperset b) =>+  StringSupersetConversion (a :: Type) (b :: Type)+  where+  convertStringUnsafe :: a -> b  instance StringSupersetConversion T.Text BS.ByteString where-    convertStringUnsafe = T.encodeUtf8+  convertStringUnsafe = T.encodeUtf8  instance StringSupersetConversion BS.ByteString T.Text where-    convertStringUnsafe = T.decodeUtf8+  convertStringUnsafe = T.decodeUtf8  instance StringSupersetConversion LT.Text LBS.ByteString where-    convertStringUnsafe = LT.encodeUtf8+  convertStringUnsafe = LT.encodeUtf8  instance StringSupersetConversion LBS.ByteString LT.Text where-    convertStringUnsafe = LT.decodeUtf8+  convertStringUnsafe = LT.decodeUtf8  instance StringSupersetConversion T.Text LT.Text where-    convertStringUnsafe = LT.fromStrict+  convertStringUnsafe = LT.fromStrict  instance StringSupersetConversion LT.Text T.Text where-    convertStringUnsafe = LT.toStrict+  convertStringUnsafe = LT.toStrict  instance StringSupersetConversion BS.ByteString LBS.ByteString where-    convertStringUnsafe = LBS.fromStrict+  convertStringUnsafe = LBS.fromStrict  instance StringSupersetConversion LBS.ByteString BS.ByteString where-    convertStringUnsafe = LBS.toStrict+  convertStringUnsafe = LBS.toStrict  ---  instance StringSupersetConversion T.Text [Unicode.Char] where-    convertStringUnsafe = T.unpack+  convertStringUnsafe = T.unpack  instance StringSupersetConversion [Unicode.Char] T.Text where-    convertStringUnsafe = T.pack+  convertStringUnsafe = T.pack  instance StringSupersetConversion LT.Text [Unicode.Char] where-    convertStringUnsafe = LT.unpack+  convertStringUnsafe = LT.unpack  instance StringSupersetConversion [Unicode.Char] LT.Text where-    convertStringUnsafe = LT.pack+  convertStringUnsafe = LT.pack  instance StringSupersetConversion BS.ByteString [Unicode.Char] where-    convertStringUnsafe = BS.Char8.unpack+  convertStringUnsafe = BS.Char8.unpack  instance StringSupersetConversion [Unicode.Char] BS.ByteString where-    convertStringUnsafe = BS.Char8.pack+  convertStringUnsafe = BS.Char8.pack  instance StringSupersetConversion LBS.ByteString [Unicode.Char] where-    convertStringUnsafe = LBS.Char8.unpack+  convertStringUnsafe = LBS.Char8.unpack  instance StringSupersetConversion [Unicode.Char] LBS.ByteString where-    convertStringUnsafe = LBS.Char8.pack+  convertStringUnsafe = LBS.Char8.pack
library/ASCII/SupersetConversion.hs-boot view
@@ -1,6 +1,9 @@ module ASCII.SupersetConversion where  import ASCII.Superset (StringSuperset)+import Data.Kind (Type) -class (StringSuperset a, StringSuperset b) => StringSupersetConversion a b where+class (StringSuperset a, StringSuperset b) =>+    StringSupersetConversion (a :: Type) (b :: Type)+  where     convertStringUnsafe :: a -> b
test/Main.hs view
@@ -1,200 +1,197 @@ module Main (main) where -import Test.Hspec- import ASCII.Case (Case (..))+import ASCII.Case qualified as Case import ASCII.CaseRefinement (ASCII'lower, ASCII'upper, asciiCaseUnsafe)+import ASCII.CaseRefinement qualified as CaseRefinement+import ASCII.Caseless qualified as CC import ASCII.Char (Char (..))+import ASCII.Char qualified as ASCII import ASCII.Refinement (ASCII, asciiUnsafe)+import ASCII.Refinement qualified as Refinement import ASCII.Superset (fromChar, fromCharList)--import qualified ASCII.Case as Case-import qualified ASCII.Caseless as CC-import qualified ASCII.CaseRefinement as CaseRefinement-import qualified ASCII.Char as ASCII-import qualified ASCII.Refinement as Refinement-import qualified ASCII.Superset as Superset--import qualified Data.Foldable as Foldable-+import ASCII.Superset qualified as Superset+import Data.Char qualified as Unicode+import Data.Foldable qualified as Foldable import Data.Function ((&)) import Data.Text (Text) import Data.Word (Word8) import Numeric.Natural (Natural)+import Test.Hspec import Prelude -import qualified Data.Char as Unicode- main :: IO () main = hspec $ do--    describe "fromChar" $ do--        it "letter" $ do-            let f x = fromChar x :: Word8-            f CapitalLetterA `shouldBe` 65--        it "to unicode" $ do-            let f = fromChar-            f CapitalLetterA `shouldBe` 'A'--        it "id" $ do-            let f x = fromChar (x :: ASCII.Char) :: ASCII.Char-            f CapitalLetterA `shouldBe` CapitalLetterA--    describe "refinement" $ do--        it "validateChar" $ do-            let f x = Refinement.validateChar x :: Maybe (ASCII Int)-            f (-1) `shouldBe` Nothing-            f 65 `shouldBe` Just (asciiUnsafe 65)-            f 97 `shouldBe` Just (asciiUnsafe 97)-            f 128 `shouldBe` Nothing--        describe "fromCharList" $ do-            it "Text" $ do-                let f x = fromCharList x :: Text-                f [CapitalLetterH, SmallLetterI, ExclamationMark] `shouldBe` "Hi!"--            it "ASCII Text" $ do-                let f x = Refinement.fromCharList x :: ASCII Text-                f [CapitalLetterH, SmallLetterI, ExclamationMark] `shouldBe` asciiUnsafe "Hi!"--        it "toCharList" $ do-            let f x = Refinement.toCharList-                          (Refinement.substituteString x :: ASCII Text)-            f "Piñata" `shouldBe` [CapitalLetterP, SmallLetterI, Substitute,-                                   SmallLetterA, SmallLetterT, SmallLetterA]--        it "substituteString" $ do-            let f x = Refinement.substituteString x :: ASCII Text-            f "Cristóbal" `shouldBe` asciiUnsafe "Crist\SUBbal"+  describe "fromChar" $ do+    it "letter" $ do+      let f x = fromChar x :: Word8+      f CapitalLetterA `shouldBe` 65 -        it "validateString" $ do-            let f x = Refinement.validateString x :: Maybe (ASCII Text)-            f "Hello" `shouldBe` Just (asciiUnsafe "Hello")-            f "Cristóbal" `shouldBe` Nothing+    it "to unicode" $ do+      let f = fromChar+      f CapitalLetterA `shouldBe` 'A' -    describe "case refinement" $ do+    it "id" $ do+      let f x = fromChar (x :: ASCII.Char) :: ASCII.Char+      f CapitalLetterA `shouldBe` CapitalLetterA -        describe "validateChar" $ do+  describe "refinement" $ do+    it "validateChar" $ do+      let f x = Refinement.validateChar x :: Maybe (ASCII Int)+      f (-1) `shouldBe` Nothing+      f 65 `shouldBe` Just (asciiUnsafe 65)+      f 97 `shouldBe` Just (asciiUnsafe 97)+      f 128 `shouldBe` Nothing -            it "lower" $ do-                let f x = CaseRefinement.validateChar x :: Maybe (ASCII'lower Int)-                f (-1) `shouldBe` Nothing-                f 65 `shouldBe` Nothing-                f 97 `shouldBe` Just (asciiCaseUnsafe 97)-                f 128 `shouldBe` Nothing+    describe "fromCharList" $ do+      it "Text" $ do+        let f x = fromCharList x :: Text+        f [CapitalLetterH, SmallLetterI, ExclamationMark] `shouldBe` "Hi!" -            it "upper" $ do-                let f x = CaseRefinement.validateChar x :: Maybe (ASCII'upper Int)-                f (-1) `shouldBe` Nothing-                f 65 `shouldBe` Just (asciiCaseUnsafe 65)-                f 97 `shouldBe` Nothing-                f 128 `shouldBe` Nothing+      it "ASCII Text" $ do+        let f x = Refinement.fromCharList x :: ASCII Text+        f [CapitalLetterH, SmallLetterI, ExclamationMark] `shouldBe` asciiUnsafe "Hi!" -        describe "fromCaselessCharList" $ do+    it "toCharList" $ do+      let f x =+            Refinement.toCharList+              (Refinement.substituteString x :: ASCII Text)+      f "Piñata"+        `shouldBe` [ CapitalLetterP,+                     SmallLetterI,+                     Substitute,+                     SmallLetterA,+                     SmallLetterT,+                     SmallLetterA+                   ] -            it "lower" $ do-                let f x = CaseRefinement.fromCaselessCharList x :: ASCII'lower Text-                f [CC.LetterH, CC.LetterI, CC.ExclamationMark] `shouldBe` asciiCaseUnsafe "hi!"+    it "substituteString" $ do+      let f x = Refinement.substituteString x :: ASCII Text+      f "Cristóbal" `shouldBe` asciiUnsafe "Crist\SUBbal" -            it "upper" $ do-                let f x = CaseRefinement.fromCaselessCharList x :: ASCII'upper Text-                f [CC.LetterH, CC.LetterI, CC.ExclamationMark] `shouldBe` asciiCaseUnsafe "HI!"+    it "validateString" $ do+      let f x = Refinement.validateString x :: Maybe (ASCII Text)+      f "Hello" `shouldBe` Just (asciiUnsafe "Hello")+      f "Cristóbal" `shouldBe` Nothing -        describe "toCaselessCharList" $ do+  describe "case refinement" $ do+    describe "validateChar" $ do+      it "lower" $ do+        let f x = CaseRefinement.validateChar x :: Maybe (ASCII'lower Int)+        f (-1) `shouldBe` Nothing+        f 65 `shouldBe` Nothing+        f 97 `shouldBe` Just (asciiCaseUnsafe 97)+        f 128 `shouldBe` Nothing -            it "lower" $ do-                let f x = CaseRefinement.toCaselessCharList (x :: ASCII'lower Text)-                f (asciiCaseUnsafe "hi!") `shouldBe` [CC.LetterH, CC.LetterI, CC.ExclamationMark]+      it "upper" $ do+        let f x = CaseRefinement.validateChar x :: Maybe (ASCII'upper Int)+        f (-1) `shouldBe` Nothing+        f 65 `shouldBe` Just (asciiCaseUnsafe 65)+        f 97 `shouldBe` Nothing+        f 128 `shouldBe` Nothing -            it "upper" $ do-                let f x = CaseRefinement.toCaselessCharList (x :: ASCII'upper Text)-                f (asciiCaseUnsafe "HI!") `shouldBe` [CC.LetterH, CC.LetterI, CC.ExclamationMark]+    describe "fromCaselessCharList" $ do+      it "lower" $ do+        let f x = CaseRefinement.fromCaselessCharList x :: ASCII'lower Text+        f [CC.LetterH, CC.LetterI, CC.ExclamationMark] `shouldBe` asciiCaseUnsafe "hi!" -        describe "substituteString" $ do+      it "upper" $ do+        let f x = CaseRefinement.fromCaselessCharList x :: ASCII'upper Text+        f [CC.LetterH, CC.LetterI, CC.ExclamationMark] `shouldBe` asciiCaseUnsafe "HI!" -            it "lower" $ do-                let f x = CaseRefinement.substituteString x :: ASCII'lower Text-                f "Cób" `shouldBe` asciiCaseUnsafe "\SUB\SUBb"+    describe "toCaselessCharList" $ do+      it "lower" $ do+        let f x = CaseRefinement.toCaselessCharList (x :: ASCII'lower Text)+        f (asciiCaseUnsafe "hi!") `shouldBe` [CC.LetterH, CC.LetterI, CC.ExclamationMark] -            it "upper" $ do-                let f x = CaseRefinement.substituteString x :: ASCII'upper Text-                f "Cób" `shouldBe` asciiCaseUnsafe "C\SUB\SUB"+      it "upper" $ do+        let f x = CaseRefinement.toCaselessCharList (x :: ASCII'upper Text)+        f (asciiCaseUnsafe "HI!") `shouldBe` [CC.LetterH, CC.LetterI, CC.ExclamationMark] -        describe "validateString" $ do+    describe "substituteString" $ do+      it "lower" $ do+        let f x = CaseRefinement.substituteString x :: ASCII'lower Text+        f "Cób" `shouldBe` asciiCaseUnsafe "\SUB\SUBb" -            it "lower" $ do-                let f x = CaseRefinement.validateString x :: Maybe (ASCII'lower Text)-                f "hello" `shouldBe` Just (asciiCaseUnsafe "hello")-                f "Hello" `shouldBe` Nothing+      it "upper" $ do+        let f x = CaseRefinement.substituteString x :: ASCII'upper Text+        f "Cób" `shouldBe` asciiCaseUnsafe "C\SUB\SUB" -            it "upper" $ do-                let f x = CaseRefinement.validateString x :: Maybe (ASCII'upper Text)-                f "HELLO" `shouldBe` Just (asciiCaseUnsafe "HELLO")-                f "Hello" `shouldBe` Nothing+    describe "validateString" $ do+      it "lower" $ do+        let f x = CaseRefinement.validateString x :: Maybe (ASCII'lower Text)+        f "hello" `shouldBe` Just (asciiCaseUnsafe "hello")+        f "Hello" `shouldBe` Nothing -    describe "case conversion" $ do+      it "upper" $ do+        let f x = CaseRefinement.validateString x :: Maybe (ASCII'upper Text)+        f "HELLO" `shouldBe` Just (asciiCaseUnsafe "HELLO")+        f "Hello" `shouldBe` Nothing -        describe "toCaseChar" $ do-            let check :: forall a. Eq a => Superset.CharSuperset a => Expectation-                check =-                    ([UpperCase, LowerCase] & Foldable.all (\c ->-                        ASCII.allCharacters & Foldable.all (\x ->-                            Superset.toCaseChar c (fromChar @a x)+  describe "case conversion" $ do+    describe "toCaseChar" $ do+      let check :: forall a. Eq a => Superset.CharSuperset a => Expectation+          check =+            ( [UpperCase, LowerCase]+                & Foldable.all+                  ( \c ->+                      ASCII.allCharacters+                        & Foldable.all+                          ( \x ->+                              Superset.toCaseChar c (fromChar @a x)                                 == fromChar @a (Case.toCase c x)-                    ))) `shouldBe` True-            it "ASCII.Char" $ check @ASCII.Char-            it "Unicode.Char" $ check @Unicode.Char-            it "Natural" $ check @Natural-            it "Int" $ check @Int-            it "Word8" $ check @Word8--        describe "toCaseString" $ do-            it "Text" $ do-                let x = "012 abc DEF ﬓ" :: Text-                Superset.toCaseString UpperCase x `shouldBe` "012 ABC DEF ﬓ"-                Superset.toCaseString LowerCase x `shouldBe` "012 abc def ﬓ"--        describe "refineStringToCase" $ do-            it "Text" $ do-                let x = asciiUnsafe "Hi!" :: ASCII Text-                CaseRefinement.refineStringToCase x `shouldBe` (asciiCaseUnsafe "HI!" :: ASCII'upper Text)-                CaseRefinement.refineStringToCase x `shouldBe` (asciiCaseUnsafe "hi!" :: ASCII'lower Text)+                          )+                  )+            )+              `shouldBe` True+      it "ASCII.Char" $ check @ASCII.Char+      it "Unicode.Char" $ check @Unicode.Char+      it "Natural" $ check @Natural+      it "Int" $ check @Int+      it "Word8" $ check @Word8 -        describe "toCasefulChar" $ do+    describe "toCaseString" $ do+      it "Text" $ do+        let x = "012 abc DEF ﬓ" :: Text+        Superset.toCaseString UpperCase x `shouldBe` "012 ABC DEF ﬓ"+        Superset.toCaseString LowerCase x `shouldBe` "012 abc def ﬓ" -            describe "lower case" $ do-                let a :: Superset.ToCasefulChar 'LowerCase char => char-                    a = Superset.toCasefulChar @'LowerCase CC.LetterA+    describe "refineStringToCase" $ do+      it "Text" $ do+        let x = asciiUnsafe "Hi!" :: ASCII Text+        CaseRefinement.refineStringToCase x `shouldBe` (asciiCaseUnsafe "HI!" :: ASCII'upper Text)+        CaseRefinement.refineStringToCase x `shouldBe` (asciiCaseUnsafe "hi!" :: ASCII'lower Text) -                it "can be Char"              $ a `shouldBe` SmallLetterA-                it "can be superset type"     $ a `shouldBe` 'a'-                it "can be case-refined type" $ a `shouldBe` (asciiCaseUnsafe 'a' :: ASCII'lower Unicode.Char)+    describe "toCasefulChar" $ do+      describe "lower case" $ do+        let a :: Superset.ToCasefulChar 'LowerCase char => char+            a = Superset.toCasefulChar @'LowerCase CC.LetterA -            describe "upper case" $ do-                let a :: Superset.ToCasefulChar 'UpperCase char => char-                    a = Superset.toCasefulChar @'UpperCase CC.LetterA+        it "can be Char" $ a `shouldBe` SmallLetterA+        it "can be superset type" $ a `shouldBe` 'a'+        it "can be case-refined type" $ a `shouldBe` (asciiCaseUnsafe 'a' :: ASCII'lower Unicode.Char) -                it "can be Char"              $ a `shouldBe` CapitalLetterA-                it "can be superset type"     $ a `shouldBe` 'A'-                it "can be case-refined type" $ a `shouldBe` (asciiCaseUnsafe 'A' :: ASCII'upper Unicode.Char)+      describe "upper case" $ do+        let a :: Superset.ToCasefulChar 'UpperCase char => char+            a = Superset.toCasefulChar @'UpperCase CC.LetterA -        describe "toCasefulString" $ do+        it "can be Char" $ a `shouldBe` CapitalLetterA+        it "can be superset type" $ a `shouldBe` 'A'+        it "can be case-refined type" $ a `shouldBe` (asciiCaseUnsafe 'A' :: ASCII'upper Unicode.Char) -            describe "lower case" $ do-                let x :: Superset.ToCasefulString 'LowerCase string => string-                    x = Superset.toCasefulString @'LowerCase [CC.LetterH, CC.LetterI, CC.ExclamationMark]+    describe "toCasefulString" $ do+      describe "lower case" $ do+        let x :: Superset.ToCasefulString 'LowerCase string => string+            x = Superset.toCasefulString @'LowerCase [CC.LetterH, CC.LetterI, CC.ExclamationMark] -                it "can be [Char]"            $ x `shouldBe` [SmallLetterH, SmallLetterI, ExclamationMark]-                it "can be superset type"     $ x `shouldBe` ("hi!" :: Text)-                it "can be case-refined type" $ x `shouldBe` (asciiCaseUnsafe "hi!" :: ASCII'lower Text)+        it "can be [Char]" $ x `shouldBe` [SmallLetterH, SmallLetterI, ExclamationMark]+        it "can be superset type" $ x `shouldBe` ("hi!" :: Text)+        it "can be case-refined type" $ x `shouldBe` (asciiCaseUnsafe "hi!" :: ASCII'lower Text) -            describe "upper case" $ do-                let x :: Superset.ToCasefulString 'UpperCase string => string-                    x = Superset.toCasefulString @'UpperCase [CC.LetterH, CC.LetterI, CC.ExclamationMark]+      describe "upper case" $ do+        let x :: Superset.ToCasefulString 'UpperCase string => string+            x = Superset.toCasefulString @'UpperCase [CC.LetterH, CC.LetterI, CC.ExclamationMark] -                it "can be [Char]"            $ x `shouldBe` [CapitalLetterH, CapitalLetterI, ExclamationMark]-                it "can be superset type"     $ x `shouldBe` ("HI!" :: Text)-                it "can be case-refined type" $ x `shouldBe` (asciiCaseUnsafe "HI!" :: ASCII'upper Text)+        it "can be [Char]" $ x `shouldBe` [CapitalLetterH, CapitalLetterI, ExclamationMark]+        it "can be superset type" $ x `shouldBe` ("HI!" :: Text)+        it "can be case-refined type" $ x `shouldBe` (asciiCaseUnsafe "HI!" :: ASCII'upper Text)