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