ascii 1.0.1.4 → 1.0.1.6
raw patch · 5 files changed
+461/−383 lines, 5 filesdep +asciidep ~basedep ~textPVP ok
version bump matches the API change (PVP)
Dependencies added: ascii
Dependency ranges changed: base, text
API changes (from Hackage documentation)
Files
- ASCII.hs +0/−379
- ascii.cabal +14/−4
- changelog.txt +5/−0
- library/ASCII.hs +370/−0
- test/test.hs +72/−0
− ASCII.hs
@@ -1,379 +0,0 @@-{- |--The __American Standard Code for Information Interchange__ (ASCII) comprises a set of 128 characters, each represented by 7 bits. 33 of these characters are /'Control' codes/; a few of these are still in use, but most are obsolete relics of the early days of computing. The other 95 are /'Printable' characters/ such as letters and numbers, mostly corresponding to the keys on an American English keyboard.--Nowadays instead of ASCII we typically work with text using an encoding such as UTF-8 that can represent the entire Unicode character set, which includes over a hundred thousand characters and is not limited to the symbols of any particular writing system or culture. However, ASCII is still relevant to network protocols; for example, we can see it in the specification of [HTTP message headers](https://tools.ietf.org/html/rfc7230#section-1.2).--There is a convenient relationship between ASCII and Unicode: the ASCII characters are the first 128 characters of the much larger Unicode character set. The [C0 Controls and Basic Latin](https://www.unicode.org/charts/PDF/U0000.pdf) section of the Unicode standard contains a list of all the ASCII characters. You may also find this list replicated in the "ASCII.Char" module; each ASCII character corresponds to a constructor of the 'ASCII.Char' type.--We do not elaborate on the semantics of the control characters here, because this information is both obsolete and restricted by copyright law. It is described by a document entitled /"Coded Character Sets - 7-Bit American National Standard Code for Information Interchange (7-Bit ASCII)"/, published by American National Standards Institute (ANSI) and available for purchase [on their website](https://webstore.ansi.org/Standards/INCITS/INCITS1986R2012).---}--module ASCII- (- {- * @Char@ -} {- $char -} Char,-- {- * Character classifications -}- {- ** Print/control groups -} {- $groups -} Group (..), charGroup, inGroup,- {- ** Upper/lower case -} {- $case -} Case (..), letterCase, isCase, toCaseChar, toCaseString,-- {- * Monomorphic conversions -} {- $monomorphicConversions -}- {- ** @Int@ -} {- $intConversions -} charToInt, intToCharMaybe, intToCharUnsafe,- {- ** @Word8@ -} {- $word8Conversions -} charToWord8, word8ToCharMaybe, word8ToCharUnsafe,- {- ** @Char@ -} {- $unicodeCharConversions -} charToUnicode, unicodeToCharMaybe, unicodeToCharUnsafe,- {- ** @String@ -} {- $unicodeStringConversions -} charListToUnicodeString, unicodeStringToCharListMaybe, unicodeStringToCharListUnsafe,- {- ** @Text@ -} {- $textConversions -} charListToText, textToCharListMaybe, textToCharListUnsafe,- {- ** @ByteString@ -} {- $byteStringConversions -} charListToByteString, byteStringToCharListMaybe, byteStringToCharListUnsafe,-- {- * Monomorphic conversions between ASCII supersets -} {- $monoSupersetConversions -}- {- ** @ByteString@ / @String@ -} byteStringToUnicodeStringMaybe, unicodeStringToByteStringMaybe,- {- ** @[Word8]@ / @String@ -} byteListToUnicodeStringMaybe, unicodeStringToByteListMaybe,-- {- * Refinement type -} {- $refinement -} {- ** @ASCII@ -} ASCII,-- {- * Polymorphic conversions -}- {- ** Validate -} validateChar, validateString,- {- ** Lift -} {- $lift -} lift,- {- ** Convert -} {- $supersetConversions -} convertCharMaybe, convertCharOrFail, convertStringMaybe, convertStringOrFail,-- {- * Classes -} {- ** @CharSuperset@ -} CharSuperset, {- ** @StringSuperset@ -} StringSuperset, {- ** @Lift@ -} Lift, {- ** @CharIso@ -} CharIso, {- ** @StringIso@ -} StringIso,-- {- * Quasi-quoters -} {- ** @char@ -} char, {- ** @string@ -} string- )- where--import ASCII.Case ( Case (..) )-import ASCII.Char ( Char )-import ASCII.Group ( Group (..) )-import ASCII.Isomorphism ( CharIso, StringIso )-import ASCII.Lift ( Lift )-import ASCII.QuasiQuoters ( char, string )-import ASCII.Refinement ( ASCII, validateChar, validateString )-import ASCII.Superset ( CharSuperset, StringSuperset )--import Control.Monad ( (>=>) )-import Control.Monad.Fail ( MonadFail )-import Data.Bool ( Bool (..) )-import Data.Function ( (.) )-import Data.Int ( Int )-import Data.Maybe ( Maybe, maybe )-import Data.Word ( Word8 )--import qualified ASCII.Case-import qualified ASCII.Group-import qualified ASCII.Isomorphism-import qualified ASCII.Lift-import qualified ASCII.Superset--import qualified Data.ByteString as BS-import qualified Data.Char as Unicode-import qualified Data.String as Unicode-import qualified Data.Text as Text--{- $setup-->>> import ASCII.Char (Char (..))->>> import Data.List (map)->>> import Data.Text (Text)->>> import Data.Word (Word8)---}--{- $char--See also: "ASCII.Char"---}--{- $groups--ASCII characters are broadly categorized into two groups: /control codes/ and /printable characters/.--See also: "ASCII.Group"---}---{- | Determine which group a particular character belongs to.-->>> map charGroup [CapitalLetterA,EndOfTransmission]-[Printable,Control]---}--charGroup :: CharIso char => char -> Group-charGroup = ASCII.Group.charGroup . ASCII.Isomorphism.toChar--{- | Test whether a character belongs to a particular ASCII group.-->>> inGroup Printable EndOfTransmission-False-->>> inGroup Control EndOfTransmission-True-->>> map (inGroup Printable) ( [-1, 5, 65, 97, 127, 130] :: [Int] )-[False,False,True,True,False,False]---}--inGroup :: CharSuperset char => Group -> char -> Bool-inGroup g = maybe False (ASCII.Group.inGroup g) . ASCII.Superset.toCharMaybe--{- $case--/Case/ is a property of letters. /A-Z/ are /upper case/ letters, and /a-z/ are /lower case/ letters. No other ASCII characters have case.--See also: "ASCII.Case"---}--{- | Determines whether a character is an ASCII letter, and if so, whether it is upper or lower case.-->>> map letterCase [SmallLetterA, CapitalLetterA, ExclamationMark]-[Just LowerCase,Just UpperCase,Nothing]-->>> map letterCase ( [string|Hey!|] :: [ASCII Word8] )-[Just UpperCase,Just LowerCase,Just LowerCase,Nothing]---}--letterCase :: CharSuperset char => char -> Maybe Case-letterCase = ASCII.Superset.toCharMaybe >=> ASCII.Case.letterCase--{- | Determines whether a character is an ASCII letter of a particular case.-->>> map (isCase UpperCase) [SmallLetterA, CapitalLetterA, ExclamationMark]-[False,True,False]-->>> map (isCase UpperCase) ( [string|Hey!|] :: [ASCII Word8] )-[True,False,False,False]-->>> map (isCase UpperCase) ( [-1, 65, 97, 150] :: [Int] )-[False,True,False,False]---}--isCase :: CharSuperset char => Case -> char -> Bool-isCase c = maybe False (ASCII.Case.isCase c) . ASCII.Superset.toCharMaybe--{- | Maps a letter character to its upper/lower case equivalent.-->>> toCaseChar UpperCase SmallLetterA-CapitalLetterA-->>> ([char|a|] :: ASCII Word8, toCaseChar UpperCase [char|a|] :: ASCII Word8)-(asciiUnsafe 97,asciiUnsafe 65)---}--toCaseChar :: CharIso char => Case -> char -> char-toCaseChar c = ASCII.Isomorphism.asChar (ASCII.Case.toCase c)--{- | Maps each of the characters in a string to its upper/lower case equivalent.-->>> toCaseString UpperCase [CapitalLetterH,SmallLetterE,SmallLetterY,ExclamationMark]-[CapitalLetterH,CapitalLetterE,CapitalLetterY,ExclamationMark]-->>> toCaseString UpperCase [string|Hey!|] :: ASCII Text-asciiUnsafe "HEY!"---}--toCaseString :: StringIso string => Case -> string -> string-toCaseString c = ASCII.Isomorphism.mapChars (ASCII.Case.toCase c)--{- $monomorphicConversions--These are a few simple monomorphic functions to convert between ASCII and types representing some other character set.--This is not intended to be an exhaustive list of all possible conversions. For more options, see "ASCII.Superset".---}--{- $intConversions--These functions convert between the ASCII 'Char' type and 'Int'.---}--{- |-->>> map charToInt [Null, CapitalLetterA, SmallLetterA, Delete]-[0,65,97,127]---}--charToInt :: Char -> Int-charToInt = ASCII.Superset.fromChar--intToCharMaybe :: Int -> Maybe Char-intToCharMaybe = ASCII.Superset.toCharMaybe--intToCharUnsafe :: Int -> Char-intToCharUnsafe = ASCII.Superset.toCharUnsafe--{- $word8Conversions--These functions convert between the ASCII 'Char' type and 'Word8'.---}--{- |-->>> map charToWord8 [Null, CapitalLetterA, SmallLetterA, Delete]-[0,65,97,127]---}--charToWord8 :: Char -> Word8-charToWord8 = ASCII.Superset.fromChar--word8ToCharMaybe :: Word8 -> Maybe Char-word8ToCharMaybe = ASCII.Superset.toCharMaybe--word8ToCharUnsafe :: Word8 -> Char-word8ToCharUnsafe = ASCII.Superset.toCharUnsafe--{- $unicodeCharConversions--These functions convert between the ASCII 'Char' type and the Unicode 'Unicode.Char' type.---}--charToUnicode :: Char -> Unicode.Char-charToUnicode = ASCII.Superset.fromChar--unicodeToCharMaybe :: Unicode.Char -> Maybe Char-unicodeToCharMaybe = ASCII.Superset.toCharMaybe--unicodeToCharUnsafe :: Unicode.Char -> Char-unicodeToCharUnsafe = ASCII.Superset.toCharUnsafe--{- $unicodeStringConversions--These functions convert between @['Char']@ (a list of ASCII characters) and 'Unicode.String' (a list of Unicode characters).---}--charListToUnicodeString :: [Char] -> Unicode.String-charListToUnicodeString = ASCII.Superset.fromCharList--unicodeStringToCharListMaybe :: Unicode.String -> Maybe [Char]-unicodeStringToCharListMaybe = ASCII.Superset.toCharListMaybe--unicodeStringToCharListUnsafe :: Unicode.String -> [Char]-unicodeStringToCharListUnsafe = ASCII.Superset.toCharListUnsafe--{- $textConversions--These functions convert between @['Char']@ and 'Text.Text'.---}--{- |-->>> charListToText [CapitalLetterH,SmallLetterI,ExclamationMark]-"Hi!"---}--charListToText :: [Char] -> Text.Text-charListToText = ASCII.Superset.fromCharList--textToCharListMaybe :: Text.Text -> Maybe [Char]-textToCharListMaybe = ASCII.Superset.toCharListMaybe--textToCharListUnsafe :: Text.Text -> [Char]-textToCharListUnsafe = ASCII.Superset.toCharListUnsafe--{- $byteStringConversions--These functions convert between @['Char']@ and 'BS.ByteString'.---}--charListToByteString :: [Char] -> BS.ByteString-charListToByteString = ASCII.Superset.fromCharList--byteStringToCharListMaybe :: BS.ByteString -> Maybe [Char]-byteStringToCharListMaybe = ASCII.Superset.toCharListMaybe--byteStringToCharListUnsafe :: BS.ByteString -> [Char]-byteStringToCharListUnsafe = ASCII.Superset.toCharListUnsafe--{- $refinement--See also: "ASCII.Refinement"---}--{- $lift--See also: "ASCII.Lift"---}--{- | Converts from ASCII to any larger type.--For example, @(lift \@ASCII.Char \@Word8)@ is the same function as 'charToWord8'.-->>> lift CapitalLetterA :: Word8-65--And @(lift \@[ASCII.Char] \@Text)@ is equivalent to 'charListToText'.-->>> lift [CapitalLetterH,SmallLetterI,ExclamationMark] :: Text-"Hi!"--Due to the highly polymorphic nature of the 'lift' function, often it must used with an explicit type signature or type application to avoid any type ambiguity.---}--lift :: Lift ascii superset => ascii -> superset-lift = ASCII.Lift.lift--{- $supersetConversions--These functions all convert from one ASCII-superset type to another, failing if any of the characters in the input is outside the ASCII character set.---}--convertCharMaybe :: (CharSuperset char1, CharSuperset char2) => char1 -> Maybe char2-convertCharMaybe = ASCII.Superset.convertCharMaybe--convertCharOrFail :: (CharSuperset char1, CharSuperset char2, MonadFail context) => char1 -> context char2-convertCharOrFail = ASCII.Superset.convertCharOrFail--convertStringMaybe :: (StringSuperset string1, StringSuperset string2) => string1 -> Maybe string2-convertStringMaybe = ASCII.Superset.convertStringMaybe--convertStringOrFail :: (StringSuperset string1, StringSuperset string2, MonadFail context) => string1 -> context string2-convertStringOrFail = ASCII.Superset.convertStringOrFail--{- $monoSupersetConversions--These functions are all specializations of 'convertStringMaybe'. They convert a string from one ASCII-superset type to another.-->>> ASCII.byteListToUnicodeStringMaybe [0x48, 0x54, 0x54, 0x50]-Just "HTTP"--If any of the characters in the input is outside the ASCII character set, the result is 'Nothing'.-->>> ASCII.byteListToUnicodeStringMaybe [0x48, 0x54, 0x54, 0x80]-Nothing---}--byteStringToUnicodeStringMaybe :: BS.ByteString -> Maybe Unicode.String-byteStringToUnicodeStringMaybe = convertStringMaybe--unicodeStringToByteStringMaybe :: Unicode.String -> Maybe BS.ByteString-unicodeStringToByteStringMaybe = convertStringMaybe--byteListToUnicodeStringMaybe :: [Word8] -> Maybe Unicode.String-byteListToUnicodeStringMaybe = convertStringMaybe--unicodeStringToByteListMaybe :: Unicode.String -> Maybe [Word8]-unicodeStringToByteListMaybe = convertStringMaybe
ascii.cabal view
@@ -1,7 +1,7 @@ cabal-version: 2.0 name: ascii-version: 1.0.1.4+version: 1.0.1.6 synopsis: The ASCII character set and encoding category: Data, Text @@ -18,8 +18,6 @@ build-type: Simple -tested-with: GHC == 9.0.1, GHC == 8.10.1, GHC == 8.8.1, GHC == 8.6.5, GHC == 8.4.3- extra-source-files: changelog.txt source-repository head@@ -30,10 +28,11 @@ default-language: Haskell2010 default-extensions: NoImplicitPrelude ghc-options: -Wall+ hs-source-dirs: library build-depends: base >= 4.11 && < 4.16 build-depends: bytestring ^>= 0.10 || ^>= 0.11- build-depends: text ^>= 1.2+ build-depends: text ^>= 1.2.3 exposed-modules: ASCII @@ -66,3 +65,14 @@ reexported-modules: Data.Ascii.Blaze reexported-modules: Data.Ascii.ByteString reexported-modules: Data.Ascii.Word8++test-suite test+ type: exitcode-stdio-1.0+ default-language: Haskell2010+ default-extensions: NoImplicitPrelude+ default-extensions: OverloadedStrings+ default-extensions: QuasiQuotes+ ghc-options: -Wall+ hs-source-dirs: test+ main-is: test.hs+ build-depends: ascii, base, text
changelog.txt view
@@ -17,3 +17,8 @@ 1.0.1.2 - 2021-02-09 - Support bytestring-0.11 1.0.1.4 - 2021-02-10 - Support GHC 9.0++1.0.1.6 - 2021-09-26++ - Add a test suite+ - Raise 'text' lower bound to 1.2.3
+ library/ASCII.hs view
@@ -0,0 +1,370 @@+{- |++The __American Standard Code for Information Interchange__ (ASCII) comprises a set of 128 characters, each represented by 7 bits. 33 of these characters are /'Control' codes/; a few of these are still in use, but most are obsolete relics of the early days of computing. The other 95 are /'Printable' characters/ such as letters and numbers, mostly corresponding to the keys on an American English keyboard.++Nowadays instead of ASCII we typically work with text using an encoding such as UTF-8 that can represent the entire Unicode character set, which includes over a hundred thousand characters and is not limited to the symbols of any particular writing system or culture. However, ASCII is still relevant to network protocols; for example, we can see it in the specification of [HTTP message headers](https://tools.ietf.org/html/rfc7230#section-1.2).++There is a convenient relationship between ASCII and Unicode: the ASCII characters are the first 128 characters of the much larger Unicode character set. The [C0 Controls and Basic Latin](https://www.unicode.org/charts/PDF/U0000.pdf) section of the Unicode standard contains a list of all the ASCII characters. You may also find this list replicated in the "ASCII.Char" module; each ASCII character corresponds to a constructor of the 'ASCII.Char' type.++We do not elaborate on the semantics of the control characters here, because this information is both obsolete and restricted by copyright law. It is described by a document entitled /"Coded Character Sets - 7-Bit American National Standard Code for Information Interchange (7-Bit ASCII)"/, published by American National Standards Institute (ANSI) and available for purchase [on their website](https://webstore.ansi.org/Standards/INCITS/INCITS1986R2012).++-}++module ASCII+ (+ {- * @Char@ -} {- $char -} Char,++ {- * Character classifications -}+ {- ** Print/control groups -} {- $groups -} Group (..), charGroup, inGroup,+ {- ** Upper/lower case -} {- $case -} Case (..), letterCase, isCase, toCaseChar, toCaseString,++ {- * Monomorphic conversions -} {- $monomorphicConversions -}+ {- ** @Int@ -} {- $intConversions -} charToInt, intToCharMaybe, intToCharUnsafe,+ {- ** @Word8@ -} {- $word8Conversions -} charToWord8, word8ToCharMaybe, word8ToCharUnsafe,+ {- ** @Char@ -} {- $unicodeCharConversions -} charToUnicode, unicodeToCharMaybe, unicodeToCharUnsafe,+ {- ** @String@ -} {- $unicodeStringConversions -} charListToUnicodeString, unicodeStringToCharListMaybe, unicodeStringToCharListUnsafe,+ {- ** @Text@ -} {- $textConversions -} charListToText, textToCharListMaybe, textToCharListUnsafe,+ {- ** @ByteString@ -} {- $byteStringConversions -} charListToByteString, byteStringToCharListMaybe, byteStringToCharListUnsafe,++ {- * Monomorphic conversions between ASCII supersets -} {- $monoSupersetConversions -}+ {- ** @ByteString@ / @String@ -} byteStringToUnicodeStringMaybe, unicodeStringToByteStringMaybe,+ {- ** @[Word8]@ / @String@ -} byteListToUnicodeStringMaybe, unicodeStringToByteListMaybe,++ {- * Refinement type -} {- $refinement -} {- ** @ASCII@ -} ASCII,++ {- * Polymorphic conversions -}+ {- ** Validate -} validateChar, validateString,+ {- ** Lift -} {- $lift -} lift,+ {- ** Convert -} {- $supersetConversions -} convertCharMaybe, convertCharOrFail, convertStringMaybe, convertStringOrFail,++ {- * Classes -} {- ** @CharSuperset@ -} CharSuperset, {- ** @StringSuperset@ -} StringSuperset, {- ** @Lift@ -} Lift, {- ** @CharIso@ -} CharIso, {- ** @StringIso@ -} StringIso,++ {- * Quasi-quoters -} {- ** @char@ -} char, {- ** @string@ -} string+ )+ where++import ASCII.Case ( Case (..) )+import ASCII.Char ( Char )+import ASCII.Group ( Group (..) )+import ASCII.Isomorphism ( CharIso, StringIso )+import ASCII.Lift ( Lift )+import ASCII.QuasiQuoters ( char, string )+import ASCII.Refinement ( ASCII, validateChar, validateString )+import ASCII.Superset ( CharSuperset, StringSuperset )++import Control.Monad ( (>=>) )+import Control.Monad.Fail ( MonadFail )+import Data.Bool ( Bool (..) )+import Data.Function ( (.) )+import Data.Int ( Int )+import Data.Maybe ( Maybe, maybe )+import Data.Word ( Word8 )++import qualified ASCII.Case+import qualified ASCII.Group+import qualified ASCII.Isomorphism+import qualified ASCII.Lift+import qualified ASCII.Superset++import qualified Data.ByteString as BS+import qualified Data.Char as Unicode+import qualified Data.String as Unicode+import qualified Data.Text as Text++{- $char++See also: "ASCII.Char"++-}++{- $groups++ASCII characters are broadly categorized into two groups: /control codes/ and /printable characters/.++See also: "ASCII.Group"++-}+++{- | Determine which group a particular character belongs to.++>>> map charGroup [CapitalLetterA,EndOfTransmission]+[Printable,Control]++-}++charGroup :: CharIso char => char -> Group+charGroup = ASCII.Group.charGroup . ASCII.Isomorphism.toChar++{- | Test whether a character belongs to a particular ASCII group.++>>> inGroup Printable EndOfTransmission+False++>>> inGroup Control EndOfTransmission+True++>>> map (inGroup Printable) ( [-1, 5, 65, 97, 127, 130] :: [Int] )+[False,False,True,True,False,False]++-}++inGroup :: CharSuperset char => Group -> char -> Bool+inGroup g = maybe False (ASCII.Group.inGroup g) . ASCII.Superset.toCharMaybe++{- $case++/Case/ is a property of letters. /A-Z/ are /upper case/ letters, and /a-z/ are /lower case/ letters. No other ASCII characters have case.++See also: "ASCII.Case"++-}++{- | Determines whether a character is an ASCII letter, and if so, whether it is upper or lower case.++>>> map letterCase [SmallLetterA, CapitalLetterA, ExclamationMark]+[Just LowerCase,Just UpperCase,Nothing]++>>> map letterCase ( [string|Hey!|] :: [ASCII Word8] )+[Just UpperCase,Just LowerCase,Just LowerCase,Nothing]++-}++letterCase :: CharSuperset char => char -> Maybe Case+letterCase = ASCII.Superset.toCharMaybe >=> ASCII.Case.letterCase++{- | Determines whether a character is an ASCII letter of a particular case.++>>> map (isCase UpperCase) [SmallLetterA, CapitalLetterA, ExclamationMark]+[False,True,False]++>>> map (isCase UpperCase) ( [string|Hey!|] :: [ASCII Word8] )+[True,False,False,False]++>>> map (isCase UpperCase) ( [-1, 65, 97, 150] :: [Int] )+[False,True,False,False]++-}++isCase :: CharSuperset char => Case -> char -> Bool+isCase c = maybe False (ASCII.Case.isCase c) . ASCII.Superset.toCharMaybe++{- | Maps a letter character to its upper/lower case equivalent.++>>> toCaseChar UpperCase SmallLetterA+CapitalLetterA++>>> ([char|a|] :: ASCII Word8, toCaseChar UpperCase [char|a|] :: ASCII Word8)+(asciiUnsafe 97,asciiUnsafe 65)++-}++toCaseChar :: CharIso char => Case -> char -> char+toCaseChar c = ASCII.Isomorphism.asChar (ASCII.Case.toCase c)++{- | Maps each of the characters in a string to its upper/lower case equivalent.++>>> toCaseString UpperCase [CapitalLetterH,SmallLetterE,SmallLetterY,ExclamationMark]+[CapitalLetterH,CapitalLetterE,CapitalLetterY,ExclamationMark]++>>> toCaseString UpperCase [string|Hey!|] :: ASCII Text+asciiUnsafe "HEY!"++-}++toCaseString :: StringIso string => Case -> string -> string+toCaseString c = ASCII.Isomorphism.mapChars (ASCII.Case.toCase c)++{- $monomorphicConversions++These are a few simple monomorphic functions to convert between ASCII and types representing some other character set.++This is not intended to be an exhaustive list of all possible conversions. For more options, see "ASCII.Superset".++-}++{- $intConversions++These functions convert between the ASCII 'Char' type and 'Int'.++-}++{- |++>>> map charToInt [Null, CapitalLetterA, SmallLetterA, Delete]+[0,65,97,127]++-}++charToInt :: Char -> Int+charToInt = ASCII.Superset.fromChar++intToCharMaybe :: Int -> Maybe Char+intToCharMaybe = ASCII.Superset.toCharMaybe++intToCharUnsafe :: Int -> Char+intToCharUnsafe = ASCII.Superset.toCharUnsafe++{- $word8Conversions++These functions convert between the ASCII 'Char' type and 'Word8'.++-}++{- |++>>> map charToWord8 [Null, CapitalLetterA, SmallLetterA, Delete]+[0,65,97,127]++-}++charToWord8 :: Char -> Word8+charToWord8 = ASCII.Superset.fromChar++word8ToCharMaybe :: Word8 -> Maybe Char+word8ToCharMaybe = ASCII.Superset.toCharMaybe++word8ToCharUnsafe :: Word8 -> Char+word8ToCharUnsafe = ASCII.Superset.toCharUnsafe++{- $unicodeCharConversions++These functions convert between the ASCII 'Char' type and the Unicode 'Unicode.Char' type.++-}++charToUnicode :: Char -> Unicode.Char+charToUnicode = ASCII.Superset.fromChar++unicodeToCharMaybe :: Unicode.Char -> Maybe Char+unicodeToCharMaybe = ASCII.Superset.toCharMaybe++unicodeToCharUnsafe :: Unicode.Char -> Char+unicodeToCharUnsafe = ASCII.Superset.toCharUnsafe++{- $unicodeStringConversions++These functions convert between @['Char']@ (a list of ASCII characters) and 'Unicode.String' (a list of Unicode characters).++-}++charListToUnicodeString :: [Char] -> Unicode.String+charListToUnicodeString = ASCII.Superset.fromCharList++unicodeStringToCharListMaybe :: Unicode.String -> Maybe [Char]+unicodeStringToCharListMaybe = ASCII.Superset.toCharListMaybe++unicodeStringToCharListUnsafe :: Unicode.String -> [Char]+unicodeStringToCharListUnsafe = ASCII.Superset.toCharListUnsafe++{- $textConversions++These functions convert between @['Char']@ and 'Text.Text'.++-}++{- |++>>> charListToText [CapitalLetterH,SmallLetterI,ExclamationMark]+"Hi!"++-}++charListToText :: [Char] -> Text.Text+charListToText = ASCII.Superset.fromCharList++textToCharListMaybe :: Text.Text -> Maybe [Char]+textToCharListMaybe = ASCII.Superset.toCharListMaybe++textToCharListUnsafe :: Text.Text -> [Char]+textToCharListUnsafe = ASCII.Superset.toCharListUnsafe++{- $byteStringConversions++These functions convert between @['Char']@ and 'BS.ByteString'.++-}++charListToByteString :: [Char] -> BS.ByteString+charListToByteString = ASCII.Superset.fromCharList++byteStringToCharListMaybe :: BS.ByteString -> Maybe [Char]+byteStringToCharListMaybe = ASCII.Superset.toCharListMaybe++byteStringToCharListUnsafe :: BS.ByteString -> [Char]+byteStringToCharListUnsafe = ASCII.Superset.toCharListUnsafe++{- $refinement++See also: "ASCII.Refinement"++-}++{- $lift++See also: "ASCII.Lift"++-}++{- | Converts from ASCII to any larger type.++For example, @(lift \@ASCII.Char \@Word8)@ is the same function as 'charToWord8'.++>>> lift CapitalLetterA :: Word8+65++And @(lift \@[ASCII.Char] \@Text)@ is equivalent to 'charListToText'.++>>> lift [CapitalLetterH,SmallLetterI,ExclamationMark] :: Text+"Hi!"++Due to the highly polymorphic nature of the 'lift' function, often it must used with an explicit type signature or type application to avoid any type ambiguity.++-}++lift :: Lift ascii superset => ascii -> superset+lift = ASCII.Lift.lift++{- $supersetConversions++These functions all convert from one ASCII-superset type to another, failing if any of the characters in the input is outside the ASCII character set.++-}++convertCharMaybe :: (CharSuperset char1, CharSuperset char2) => char1 -> Maybe char2+convertCharMaybe = ASCII.Superset.convertCharMaybe++convertCharOrFail :: (CharSuperset char1, CharSuperset char2, MonadFail context) => char1 -> context char2+convertCharOrFail = ASCII.Superset.convertCharOrFail++convertStringMaybe :: (StringSuperset string1, StringSuperset string2) => string1 -> Maybe string2+convertStringMaybe = ASCII.Superset.convertStringMaybe++convertStringOrFail :: (StringSuperset string1, StringSuperset string2, MonadFail context) => string1 -> context string2+convertStringOrFail = ASCII.Superset.convertStringOrFail++{- $monoSupersetConversions++These functions are all specializations of 'convertStringMaybe'. They convert a string from one ASCII-superset type to another.++>>> ASCII.byteListToUnicodeStringMaybe [0x48, 0x54, 0x54, 0x50]+Just "HTTP"++If any of the characters in the input is outside the ASCII character set, the result is 'Nothing'.++>>> ASCII.byteListToUnicodeStringMaybe [0x48, 0x54, 0x54, 0x80]+Nothing++-}++byteStringToUnicodeStringMaybe :: BS.ByteString -> Maybe Unicode.String+byteStringToUnicodeStringMaybe = convertStringMaybe++unicodeStringToByteStringMaybe :: Unicode.String -> Maybe BS.ByteString+unicodeStringToByteStringMaybe = convertStringMaybe++byteListToUnicodeStringMaybe :: [Word8] -> Maybe Unicode.String+byteListToUnicodeStringMaybe = convertStringMaybe++unicodeStringToByteListMaybe :: Unicode.String -> Maybe [Word8]+unicodeStringToByteListMaybe = convertStringMaybe
+ test/test.hs view
@@ -0,0 +1,72 @@+module Main where++import ASCII++import ASCII.Char (Char (..))+import ASCII.Refinement (asciiUnsafe)++import Control.Applicative (Applicative (..))+import Control.Monad (Monad (..))+import Data.Bool (Bool (..))+import Data.Eq (Eq ((==)))+import Data.Function ((.), ($))+import Data.Functor (Functor (..))+import Data.Int (Int)+import Data.List (intercalate, map, null)+import Data.Maybe (Maybe (..))+import Data.Semigroup ((<>))+import Data.Text (Text)+import Data.Word (Word8)+import Numeric.Natural (Natural)+import System.Exit (die)+import System.IO (IO, putStrLn)+import Text.Show (show)++main :: IO ()+main = dieIfFailures $ do+ test 1 $ map charGroup [CapitalLetterA, EndOfTransmission] == [Printable, Control]+ test 2 $ inGroup Printable EndOfTransmission == False+ test 3 $ inGroup Control EndOfTransmission == True+ test 4 $ map (inGroup Printable) ([-1, 5, 65, 97, 127, 130] :: [Int]) == [False, False, True, True, False, False]+ test 5 $ map letterCase [SmallLetterA, CapitalLetterA, ExclamationMark] == [Just LowerCase, Just UpperCase, Nothing]+ test 6 $ map letterCase ([string|Hey!|] :: [ASCII Word8]) == [Just UpperCase, Just LowerCase, Just LowerCase, Nothing]+ test 7 $ map (isCase UpperCase) [SmallLetterA, CapitalLetterA, ExclamationMark] == [False, True, False]+ test 8 $ map (isCase UpperCase) ([string|Hey!|] :: [ASCII Word8]) == [True, False, False, False]+ test 9 $ map (isCase UpperCase) ([-1, 65, 97, 150] :: [Int]) == [False, True, False, False]+ test 10 $ toCaseChar UpperCase SmallLetterA == CapitalLetterA+ test 11 $ ([char|a|] :: ASCII Word8, toCaseChar UpperCase [char|a|] :: ASCII Word8) == (asciiUnsafe 97, asciiUnsafe 65)+ test 12 $ toCaseString UpperCase [CapitalLetterH,SmallLetterE,SmallLetterY,ExclamationMark] == [CapitalLetterH, CapitalLetterE, CapitalLetterY, ExclamationMark]+ test 13 $ (toCaseString UpperCase [string|Hey!|] :: ASCII Text) == asciiUnsafe "HEY!"+ test 14 $ map charToInt [Null, CapitalLetterA, SmallLetterA, Delete] == [0, 65, 97, 127]+ test 15 $ map charToWord8 [Null, CapitalLetterA, SmallLetterA, Delete] == [0, 65, 97, 127]+ test 16 $ charListToText [CapitalLetterH, SmallLetterI, ExclamationMark] == "Hi!"+ test 17 $ (lift CapitalLetterA :: Word8) == 65+ test 18 $ (lift [CapitalLetterH,SmallLetterI,ExclamationMark] :: Text) == "Hi!"+ test 19 $ ASCII.byteListToUnicodeStringMaybe [0x48, 0x54, 0x54, 0x50] == Just "HTTP"+ test 20 $ ASCII.byteListToUnicodeStringMaybe [0x48, 0x54, 0x54, 0x80] == Nothing++dieIfFailures :: Failures a -> IO a+dieIfFailures (Failures fs x) =+ if null fs+ then do putStrLn "💯"; return x+ else die $ intercalate " " (map (("🔥" <> ) . show) fs)++type TestNumber = Natural++test :: TestNumber -> Bool -> Failures ()+test n t = Failures (if t then [] else [n]) ()++data Failures a = Failures [TestNumber] a++instance Functor Failures+ where+ fmap f (Failures a x) = Failures a (f x)++instance Applicative Failures+ where+ pure x = Failures [] x+ Failures a f <*> Failures b x = Failures (a <> b) (f x)++instance Monad Failures+ where+ Failures a x >>= f = let Failures b y = f x in Failures (a <> b) y