ascii-predicates 1.0.0.4 → 1.0.0.6
raw patch · 9 files changed
+497/−411 lines, 9 filesdep +ascii-predicatesdep ~ascii-chardep ~basePVP ok
version bump matches the API change (PVP)
Dependencies added: ascii-predicates
Dependency ranges changed: ascii-char, base
API changes (from Hackage documentation)
Files
- ASCII/Lists.hs +0/−83
- ASCII/ListsAndPredicates.hs +0/−54
- ASCII/Predicates.hs +0/−271
- ascii-predicates.cabal +13/−3
- changelog.txt +1/−0
- library/ASCII/Lists.hs +76/−0
- library/ASCII/ListsAndPredicates.hs +47/−0
- library/ASCII/Predicates.hs +271/−0
- test/test.hs +89/−0
− ASCII/Lists.hs
@@ -1,83 +0,0 @@-module ASCII.Lists- (- {- * Lists -}- {- ** Every character -} all,- {- ** Group-related -} printableCharacters, controlCodes,- {- ** Letter-related -} letters, capitalLetters, smallLetters,- {- ** Number-related -} digits, octDigits, hexDigits, numbers- {- * Notes -} {- $notes -}- )- where--import ASCII.Char ( Char (..) )-import Data.List ( (++) )-import Prelude ( Enum, enumFromTo,- Bounded (..), minBound, maxBound )--{- $setup-->>> import Data.Eq ((==))->>> import qualified Data.List---}---- | All 128 ASCII characters, listed in order from 'Null' to 'Delete'.--all :: [Char]-all = enumFromTo minBound maxBound---- | Characters in the 'Printable' group: 'Space', 'ExclamationMark', 'QuotationMark', 'NumberSign', 'DollarSign', 'PercentSign', 'Ampersand', 'Apostrophe', 'LeftParenthesis', 'RightParenthesis', 'Asterisk', 'PlusSign', 'Comma', 'HyphenMinus', 'FullStop', 'Slash', 'Digit0', 'Digit1', 'Digit2', 'Digit3', 'Digit4', 'Digit5', 'Digit6', 'Digit7', 'Digit8', 'Digit9', 'Colon', 'Semicolon', 'LessThanSign', 'EqualsSign', 'GreaterThanSign', 'QuestionMark', 'AtSign', 'CapitalLetterA', 'CapitalLetterB', 'CapitalLetterC', 'CapitalLetterD', 'CapitalLetterE', 'CapitalLetterF', 'CapitalLetterG', 'CapitalLetterH', 'CapitalLetterI', 'CapitalLetterJ', 'CapitalLetterK', 'CapitalLetterL', 'CapitalLetterM', 'CapitalLetterN', 'CapitalLetterO', 'CapitalLetterP', 'CapitalLetterQ', 'CapitalLetterR', 'CapitalLetterS', 'CapitalLetterT', 'CapitalLetterU', 'CapitalLetterV', 'CapitalLetterW', 'CapitalLetterX', 'CapitalLetterY', 'CapitalLetterZ', 'LeftSquareBracket', 'Backslash', 'RightSquareBracket', 'Caret', 'Underscore', 'GraveAccent', 'SmallLetterA', 'SmallLetterB', 'SmallLetterC', 'SmallLetterD', 'SmallLetterE', 'SmallLetterF', 'SmallLetterG', 'SmallLetterH', 'SmallLetterI', 'SmallLetterJ', 'SmallLetterK', 'SmallLetterL', 'SmallLetterM', 'SmallLetterN', 'SmallLetterO', 'SmallLetterP', 'SmallLetterQ', 'SmallLetterR', 'SmallLetterS', 'SmallLetterT', 'SmallLetterU', 'SmallLetterV', 'SmallLetterW', 'SmallLetterX', 'SmallLetterY', 'SmallLetterZ', 'LeftCurlyBracket', 'VerticalLine', 'RightCurlyBracket', 'Tilde'.--printableCharacters :: [Char]-printableCharacters = enumFromTo Space Tilde---- | Characters in the 'Control' group: 'Null', 'StartOfHeading', 'StartOfText', 'EndOfText', 'EndOfTransmission', 'Enquiry', 'Acknowledgement', 'Bell', 'Backspace', 'HorizontalTab', 'LineFeed', 'VerticalTab', 'FormFeed', 'CarriageReturn', 'ShiftOut', 'ShiftIn', 'DataLinkEscape', 'DeviceControl1', 'DeviceControl2', 'DeviceControl3', 'DeviceControl4', 'NegativeAcknowledgement', 'SynchronousIdle', 'EndOfTransmissionBlock', 'Cancel', 'EndOfMedium', 'Substitute', 'Escape', 'FileSeparator', 'GroupSeparator', 'RecordSeparator', 'UnitSeparator', 'Delete'.--controlCodes :: [Char]-controlCodes = enumFromTo Null UnitSeparator ++ [Delete]---- | Letters: 'CapitalLetterA', 'CapitalLetterB', 'CapitalLetterC', 'CapitalLetterD', 'CapitalLetterE', 'CapitalLetterF', 'CapitalLetterG', 'CapitalLetterH', 'CapitalLetterI', 'CapitalLetterJ', 'CapitalLetterK', 'CapitalLetterL', 'CapitalLetterM', 'CapitalLetterN', 'CapitalLetterO', 'CapitalLetterP', 'CapitalLetterQ', 'CapitalLetterR', 'CapitalLetterS', 'CapitalLetterT', 'CapitalLetterU', 'CapitalLetterV', 'CapitalLetterW', 'CapitalLetterX', 'CapitalLetterY', 'CapitalLetterZ', 'SmallLetterA', 'SmallLetterB', 'SmallLetterC', 'SmallLetterD', 'SmallLetterE', 'SmallLetterF', 'SmallLetterG', 'SmallLetterH', 'SmallLetterI', 'SmallLetterJ', 'SmallLetterK', 'SmallLetterL', 'SmallLetterM', 'SmallLetterN', 'SmallLetterO', 'SmallLetterP', 'SmallLetterQ', 'SmallLetterR', 'SmallLetterS', 'SmallLetterT', 'SmallLetterU', 'SmallLetterV', 'SmallLetterW', 'SmallLetterX', 'SmallLetterY', 'SmallLetterZ'.--letters :: [Char]-letters = capitalLetters ++ smallLetters---- | Capital letters: 'CapitalLetterA', 'CapitalLetterB', 'CapitalLetterC', 'CapitalLetterD', 'CapitalLetterE', 'CapitalLetterF', 'CapitalLetterG', 'CapitalLetterH', 'CapitalLetterI', 'CapitalLetterJ', 'CapitalLetterK', 'CapitalLetterL', 'CapitalLetterM', 'CapitalLetterN', 'CapitalLetterO', 'CapitalLetterP', 'CapitalLetterQ', 'CapitalLetterR', 'CapitalLetterS', 'CapitalLetterT', 'CapitalLetterU', 'CapitalLetterV', 'CapitalLetterW', 'CapitalLetterX', 'CapitalLetterY', 'CapitalLetterZ'.--capitalLetters :: [Char]-capitalLetters = enumFromTo CapitalLetterA CapitalLetterZ---- | Small letters: 'SmallLetterA', 'SmallLetterB', 'SmallLetterC', 'SmallLetterD', 'SmallLetterE', 'SmallLetterF', 'SmallLetterG', 'SmallLetterH', 'SmallLetterI', 'SmallLetterJ', 'SmallLetterK', 'SmallLetterL', 'SmallLetterM', 'SmallLetterN', 'SmallLetterO', 'SmallLetterP', 'SmallLetterQ', 'SmallLetterR', 'SmallLetterS', 'SmallLetterT', 'SmallLetterU', 'SmallLetterV', 'SmallLetterW', 'SmallLetterX', 'SmallLetterY', 'SmallLetterZ'.--smallLetters :: [Char]-smallLetters = enumFromTo SmallLetterA SmallLetterZ---- | Digits: 'Digit0', 'Digit1', 'Digit2', 'Digit3', 'Digit4', 'Digit5', 'Digit6', 'Digit7', 'Digit8', 'Digit9'.--digits :: [Char]-digits = enumFromTo Digit0 Digit9---- | Octal digits: 'Digit0', 'Digit1', 'Digit2', 'Digit3', 'Digit4', 'Digit5', 'Digit6', 'Digit7'.--octDigits :: [Char]-octDigits = enumFromTo Digit0 Digit7---- | Hexidecimal digits: 'Digit0', 'Digit1', 'Digit2', 'Digit3', 'Digit4', 'Digit5', 'Digit6', 'Digit7', 'Digit8', 'Digit9', 'CapitalLetterA', 'CapitalLetterB', 'CapitalLetterC', 'CapitalLetterD', 'CapitalLetterE', 'CapitalLetterF', 'SmallLetterA', 'SmallLetterB', 'SmallLetterC', 'SmallLetterD', 'SmallLetterE', 'SmallLetterF'.--hexDigits :: [Char]-hexDigits = digits ++ enumFromTo CapitalLetterA CapitalLetterF ++ enumFromTo SmallLetterA SmallLetterF---- | Synonym for 'digits'.--numbers :: [Char]-numbers = digits--{- $notes--Each list is sorted in ascending order.-->>> lists = [all, printableCharacters, controlCodes, letters, capitalLetters, smallLetters, digits, octDigits, hexDigits, numbers]-->>> Data.List.all (\xs -> Data.List.sort xs == xs) lists-True---}
− ASCII/ListsAndPredicates.hs
@@ -1,54 +0,0 @@-module ASCII.ListsAndPredicates- (- {- * Re-exported modules -} module ASCII.Lists, module ASCII.Predicates- {- * Notes -} {- $notes -}- )- where--import ASCII.Lists-import ASCII.Predicates--{- $setup-->>> import Data.Eq ((==))->>> import Data.List (filter)---}--{- $notes--The two modules re-exported here present the same information in two different forms:-- - As a list of all ASCII characters with some classification;- - As a function that tests whether a particular character belongs to the classification.--Each list contains exactly the characters for which its corresponding predicate is true.-->>> controlCodes == filter isControl all-True-->>> printableCharacters == filter isPrint all-True-->>> letters == filter isLetter all-True-->>> capitalLetters == filter isUpper all-True-->>> smallLetters == filter isLower all-True-->>> digits == filter isDigit all-True-->>> numbers == filter isNumber all-True-->>> octDigits == filter isOctDigit all-True-->>> hexDigits == filter isHexDigit all-True---}
− ASCII/Predicates.hs
@@ -1,271 +0,0 @@-module ASCII.Predicates- (- {- * Group predicates -} isControl, isPrint,- {- * Case predicates -} isLower, isUpper,- {- * Letter predicates -} isLetter, isAlpha,- {- * Number predicates -} isDigit, isOctDigit, isHexDigit, isNumber,- {- * Miscellaneous predicates -} isSpace, isAlphaNum, isMark, isPunctuation, isSymbol, isSeparator- {- * Notes -} {- $notes -}- )- where--import ASCII.Char ( Char (..) )-import Data.Bool ( Bool (..), otherwise )-import Data.Eq ( (==) )-import Data.Function ( (.) )-import Data.Ord ( (<), (<=), (>=) )--import qualified ASCII.Char as Char-import qualified Data.Bool as Bool-import qualified Data.List as List--{- | Returns True for control characters.--This function is analogous to 'Data.Char.isControl' in the "Data.Char" module.---}--isControl :: Char -> Bool-isControl x =- case x of- _ | (x < Char.Space) -> True- Char.Delete -> True- _ -> False--{- | Returns True for printable characters.--This function is analogous to 'Data.Char.isPrint' in the "Data.Char" module.---}--isPrint :: Char -> Bool-isPrint = Bool.not . isControl--{- | Returns True for lower-case letters, from 'SmallLetterA' to 'SmallLetterZ'.--This function is analogous to 'Data.Char.isLower' in the "Data.Char" module.---}--isLower :: Char -> Bool-isLower x = (Bool.&&) (x >= SmallLetterA) (x <= SmallLetterZ)--{- | Returns True for upper-case letters, from 'CapitalLetterA' to 'CapitalLetterZ'.--This function is analogous to 'Data.Char.isUpper' in the "Data.Char" module.---}--isUpper :: Char -> Bool-isUpper x = (Bool.&&) (x >= CapitalLetterA) (x <= CapitalLetterZ)--{- | Returns True for letters:--- 'SmallLetterA' to 'SmallLetterZ'-- 'CapitalLetterA' to 'CapitalLetterZ'--This function is analogous to 'Data.Char.isLetter' in the "Data.Char" module.---}--isLetter :: Char -> Bool-isLetter x = (Bool.||) (isLower x) (isUpper x)--{- | Synonym for 'isLetter'.--This function is analogous to 'Data.Char.isAlpha' in the "Data.Char" module.---}--isAlpha :: Char -> Bool-isAlpha = isLetter--{- | Returns True for the characters from 'Digit0' to 'Digit9'.--This function is analogous to 'Data.Char.isDigit' in the "Data.Char" module.---}--isDigit :: Char -> Bool-isDigit x = (Bool.&&) (x >= Digit0) (x <= Digit9)--{- | Returns True for the characters from 'Digit0' to 'Digit7'.--This function is analogous to 'Data.Char.isOctDigit' in the "Data.Char" module.---}--isOctDigit :: Char -> Bool-isOctDigit x = (Bool.&&) (x >= Digit0) (x <= Digit7)--{- | Returns True for characters in any of the following ranges:--- 'Digit0' to 'Digit9'-- 'CapitalLetterA' to 'CapitalLetterF'-- 'SmallLetterA' to 'SmallLetterF'--This function is analogous to 'Data.Char.isHexDigit' in the "Data.Char" module.---}--isHexDigit :: Char -> Bool-isHexDigit x | isDigit x = True- | (Bool.&&) (x >= CapitalLetterA) (x <= CapitalLetterF) = True- | (Bool.&&) (x >= SmallLetterA) (x <= SmallLetterF) = True- | otherwise = False--{- | Synonym for 'isDigit'.--In the "Data.Char" module, 'Data.Char.isDigit' selects only the ASCII digits 0 through 9, and 'Data.Char.isNumber' selects a wider set of characters because the full Unicode character set contains more numeric characters than just the ASCII digits. In this module, these two functions are redundant, but we include this synonym for compatibility with "Data.Char".---}--isNumber :: Char -> Bool-isNumber = isDigit--{- | Returns True for the following characters:--- 'Space'-- 'HorizontalTab'-- 'LineFeed'-- 'VerticalTab'-- 'FormFeed'-- 'CarriageReturn'--This function is analogous to 'Data.Char.isSpace' in the "Data.Char" module.---}--isSpace :: Char -> Bool-isSpace Space = True-isSpace x = (Bool.&&) (x >= HorizontalTab) (x <= CarriageReturn)---- | This function is analogous to 'Data.Char.isAlphaNum' in the "Data.Char" module.--isAlphaNum :: Char -> Bool-isAlphaNum x = (Bool.||) (isAlpha x) (isDigit x)---- | Selects mark characters, for example accents and the like, which combine with preceding characters. This always returns False because ASCII does not include any mark characters. This function is included only for compatibility with 'Data.Char.isMark' in the "Data.Char" module.--isMark :: Char -> Bool-isMark _ = False--{- | Returns True for the following characters:--- 'ExclamationMark'-- 'QuotationMark'-- 'NumberSign'-- 'PercentSign'-- 'Ampersand'-- 'Apostrophe'-- 'LeftParenthesis'-- 'RightParenthesis'-- 'Asterisk'-- 'Comma'-- 'HyphenMinus'-- 'FullStop'-- 'Slash'-- 'Colon'-- 'Semicolon'-- 'QuestionMark'-- 'AtSign'-- 'LeftSquareBracket'-- 'Backslash'-- 'RightSquareBracket'-- 'Underscore'-- 'LeftCurlyBracket'-- 'RightCurlyBracket'--This function is analogous to 'Data.Char.isPunctuation' in the "Data.Char" module.---}--isPunctuation :: Char -> Bool-isPunctuation = (`List.elem` [ExclamationMark, QuotationMark, NumberSign, PercentSign, Ampersand, Apostrophe, LeftParenthesis, RightParenthesis, Asterisk, Comma, HyphenMinus, FullStop, Slash, Colon, Semicolon, QuestionMark, AtSign, LeftSquareBracket, Backslash, RightSquareBracket, Underscore, LeftCurlyBracket, RightCurlyBracket])--{- | Returns True for the following characters:--- 'DollarSign'-- 'PlusSign'-- 'LessThanSign'-- 'EqualsSign'-- 'GreaterThanSign'-- 'Caret'-- 'GraveAccent'-- 'VerticalLine'-- 'Tilde'--This function is analogous to 'Data.Char.isSymbol' in the "Data.Char" module.---}--isSymbol :: Char -> Bool-isSymbol = (`List.elem` [DollarSign, PlusSign, LessThanSign, EqualsSign, GreaterThanSign, Caret, GraveAccent, VerticalLine, Tilde])--{- | Returns True if the character is 'Space'.--This function is analogous to 'Data.Char.isSeparator' in the "Data.Char" module.---}--isSeparator :: Char -> Bool-isSeparator = (== Space)--{- $notes--This module defines drop-in replacements for closely related definitions of the same name in the "Data.Char" module.-->>> import qualified Data.Char->>> import qualified Data.List->>> convert = Data.Char.chr . ASCII.Char.toInt->>> eq f g = Data.List.all (\x -> f x == g (convert x)) ASCII.Char.allCharacters-->>> eq isControl Data.Char.isControl-True-->>> eq isSpace Data.Char.isSpace-True-->>> eq isLower Data.Char.isLower-True-->>> eq isUpper Data.Char.isUpper-True-->>> eq isAlpha Data.Char.isAlpha-True-->>> eq isAlphaNum Data.Char.isAlphaNum-True-->>> eq isPrint Data.Char.isPrint-True-->>> eq isDigit Data.Char.isDigit-True-->>> eq isOctDigit Data.Char.isOctDigit-True-->>> eq isHexDigit Data.Char.isHexDigit-True-->>> eq isLetter Data.Char.isLetter-True-->>> eq isMark Data.Char.isMark-True-->>> eq isNumber Data.Char.isNumber-True-->>> eq isPunctuation Data.Char.isPunctuation-True-->>> eq isSymbol Data.Char.isSymbol-True-->>> eq isSeparator Data.Char.isSeparator-True---}
ascii-predicates.cabal view
@@ -1,7 +1,7 @@ cabal-version: 2.0 name: ascii-predicates-version: 1.0.0.4+version: 1.0.0.6 synopsis: Various categorizations of ASCII characters 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,6 +28,7 @@ default-language: Haskell2010 default-extensions: NoImplicitPrelude ghc-options: -Wall+ hs-source-dirs: library build-depends: ascii-char ^>= 1.0 @@ -38,3 +37,14 @@ exposed-modules: ASCII.Predicates exposed-modules: ASCII.Lists exposed-modules: ASCII.ListsAndPredicates++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-char, ascii-predicates, base
changelog.txt view
@@ -1,3 +1,4 @@ 1.0.0.0 - 2020-05-05 - Initial release 1.0.0.2 - 2020-05-18 - Support GHC 8.10 1.0.0.4 - 2021-02-20 - Support GHC 9.0+1.0.0.6 - 2021-09-26 - Add a test suite
+ library/ASCII/Lists.hs view
@@ -0,0 +1,76 @@+module ASCII.Lists+ (+ {- * Lists -}+ {- ** Every character -} all,+ {- ** Group-related -} printableCharacters, controlCodes,+ {- ** Letter-related -} letters, capitalLetters, smallLetters,+ {- ** Number-related -} digits, octDigits, hexDigits, numbers+ {- * Notes -} {- $notes -}+ )+ where++import ASCII.Char ( Char (..) )+import Data.List ( (++) )+import Prelude ( enumFromTo,+ Bounded (..), minBound, maxBound )++-- | All 128 ASCII characters, listed in order from 'Null' to 'Delete'.++all :: [Char]+all = enumFromTo minBound maxBound++-- | Characters in the 'Printable' group: 'Space', 'ExclamationMark', 'QuotationMark', 'NumberSign', 'DollarSign', 'PercentSign', 'Ampersand', 'Apostrophe', 'LeftParenthesis', 'RightParenthesis', 'Asterisk', 'PlusSign', 'Comma', 'HyphenMinus', 'FullStop', 'Slash', 'Digit0', 'Digit1', 'Digit2', 'Digit3', 'Digit4', 'Digit5', 'Digit6', 'Digit7', 'Digit8', 'Digit9', 'Colon', 'Semicolon', 'LessThanSign', 'EqualsSign', 'GreaterThanSign', 'QuestionMark', 'AtSign', 'CapitalLetterA', 'CapitalLetterB', 'CapitalLetterC', 'CapitalLetterD', 'CapitalLetterE', 'CapitalLetterF', 'CapitalLetterG', 'CapitalLetterH', 'CapitalLetterI', 'CapitalLetterJ', 'CapitalLetterK', 'CapitalLetterL', 'CapitalLetterM', 'CapitalLetterN', 'CapitalLetterO', 'CapitalLetterP', 'CapitalLetterQ', 'CapitalLetterR', 'CapitalLetterS', 'CapitalLetterT', 'CapitalLetterU', 'CapitalLetterV', 'CapitalLetterW', 'CapitalLetterX', 'CapitalLetterY', 'CapitalLetterZ', 'LeftSquareBracket', 'Backslash', 'RightSquareBracket', 'Caret', 'Underscore', 'GraveAccent', 'SmallLetterA', 'SmallLetterB', 'SmallLetterC', 'SmallLetterD', 'SmallLetterE', 'SmallLetterF', 'SmallLetterG', 'SmallLetterH', 'SmallLetterI', 'SmallLetterJ', 'SmallLetterK', 'SmallLetterL', 'SmallLetterM', 'SmallLetterN', 'SmallLetterO', 'SmallLetterP', 'SmallLetterQ', 'SmallLetterR', 'SmallLetterS', 'SmallLetterT', 'SmallLetterU', 'SmallLetterV', 'SmallLetterW', 'SmallLetterX', 'SmallLetterY', 'SmallLetterZ', 'LeftCurlyBracket', 'VerticalLine', 'RightCurlyBracket', 'Tilde'.++printableCharacters :: [Char]+printableCharacters = enumFromTo Space Tilde++-- | Characters in the 'Control' group: 'Null', 'StartOfHeading', 'StartOfText', 'EndOfText', 'EndOfTransmission', 'Enquiry', 'Acknowledgement', 'Bell', 'Backspace', 'HorizontalTab', 'LineFeed', 'VerticalTab', 'FormFeed', 'CarriageReturn', 'ShiftOut', 'ShiftIn', 'DataLinkEscape', 'DeviceControl1', 'DeviceControl2', 'DeviceControl3', 'DeviceControl4', 'NegativeAcknowledgement', 'SynchronousIdle', 'EndOfTransmissionBlock', 'Cancel', 'EndOfMedium', 'Substitute', 'Escape', 'FileSeparator', 'GroupSeparator', 'RecordSeparator', 'UnitSeparator', 'Delete'.++controlCodes :: [Char]+controlCodes = enumFromTo Null UnitSeparator ++ [Delete]++-- | Letters: 'CapitalLetterA', 'CapitalLetterB', 'CapitalLetterC', 'CapitalLetterD', 'CapitalLetterE', 'CapitalLetterF', 'CapitalLetterG', 'CapitalLetterH', 'CapitalLetterI', 'CapitalLetterJ', 'CapitalLetterK', 'CapitalLetterL', 'CapitalLetterM', 'CapitalLetterN', 'CapitalLetterO', 'CapitalLetterP', 'CapitalLetterQ', 'CapitalLetterR', 'CapitalLetterS', 'CapitalLetterT', 'CapitalLetterU', 'CapitalLetterV', 'CapitalLetterW', 'CapitalLetterX', 'CapitalLetterY', 'CapitalLetterZ', 'SmallLetterA', 'SmallLetterB', 'SmallLetterC', 'SmallLetterD', 'SmallLetterE', 'SmallLetterF', 'SmallLetterG', 'SmallLetterH', 'SmallLetterI', 'SmallLetterJ', 'SmallLetterK', 'SmallLetterL', 'SmallLetterM', 'SmallLetterN', 'SmallLetterO', 'SmallLetterP', 'SmallLetterQ', 'SmallLetterR', 'SmallLetterS', 'SmallLetterT', 'SmallLetterU', 'SmallLetterV', 'SmallLetterW', 'SmallLetterX', 'SmallLetterY', 'SmallLetterZ'.++letters :: [Char]+letters = capitalLetters ++ smallLetters++-- | Capital letters: 'CapitalLetterA', 'CapitalLetterB', 'CapitalLetterC', 'CapitalLetterD', 'CapitalLetterE', 'CapitalLetterF', 'CapitalLetterG', 'CapitalLetterH', 'CapitalLetterI', 'CapitalLetterJ', 'CapitalLetterK', 'CapitalLetterL', 'CapitalLetterM', 'CapitalLetterN', 'CapitalLetterO', 'CapitalLetterP', 'CapitalLetterQ', 'CapitalLetterR', 'CapitalLetterS', 'CapitalLetterT', 'CapitalLetterU', 'CapitalLetterV', 'CapitalLetterW', 'CapitalLetterX', 'CapitalLetterY', 'CapitalLetterZ'.++capitalLetters :: [Char]+capitalLetters = enumFromTo CapitalLetterA CapitalLetterZ++-- | Small letters: 'SmallLetterA', 'SmallLetterB', 'SmallLetterC', 'SmallLetterD', 'SmallLetterE', 'SmallLetterF', 'SmallLetterG', 'SmallLetterH', 'SmallLetterI', 'SmallLetterJ', 'SmallLetterK', 'SmallLetterL', 'SmallLetterM', 'SmallLetterN', 'SmallLetterO', 'SmallLetterP', 'SmallLetterQ', 'SmallLetterR', 'SmallLetterS', 'SmallLetterT', 'SmallLetterU', 'SmallLetterV', 'SmallLetterW', 'SmallLetterX', 'SmallLetterY', 'SmallLetterZ'.++smallLetters :: [Char]+smallLetters = enumFromTo SmallLetterA SmallLetterZ++-- | Digits: 'Digit0', 'Digit1', 'Digit2', 'Digit3', 'Digit4', 'Digit5', 'Digit6', 'Digit7', 'Digit8', 'Digit9'.++digits :: [Char]+digits = enumFromTo Digit0 Digit9++-- | Octal digits: 'Digit0', 'Digit1', 'Digit2', 'Digit3', 'Digit4', 'Digit5', 'Digit6', 'Digit7'.++octDigits :: [Char]+octDigits = enumFromTo Digit0 Digit7++-- | Hexidecimal digits: 'Digit0', 'Digit1', 'Digit2', 'Digit3', 'Digit4', 'Digit5', 'Digit6', 'Digit7', 'Digit8', 'Digit9', 'CapitalLetterA', 'CapitalLetterB', 'CapitalLetterC', 'CapitalLetterD', 'CapitalLetterE', 'CapitalLetterF', 'SmallLetterA', 'SmallLetterB', 'SmallLetterC', 'SmallLetterD', 'SmallLetterE', 'SmallLetterF'.++hexDigits :: [Char]+hexDigits = digits ++ enumFromTo CapitalLetterA CapitalLetterF ++ enumFromTo SmallLetterA SmallLetterF++-- | Synonym for 'digits'.++numbers :: [Char]+numbers = digits++{- $notes++Each list is sorted in ascending order.++>>> lists = [all, printableCharacters, controlCodes, letters, capitalLetters, smallLetters, digits, octDigits, hexDigits, numbers]++>>> Data.List.all (\xs -> Data.List.sort xs == xs) lists+True++-}
+ library/ASCII/ListsAndPredicates.hs view
@@ -0,0 +1,47 @@+module ASCII.ListsAndPredicates+ (+ {- * Re-exported modules -} module ASCII.Lists, module ASCII.Predicates+ {- * Notes -} {- $notes -}+ )+ where++import ASCII.Lists+import ASCII.Predicates++{- $notes++The two modules re-exported here present the same information in two different forms:++ - As a list of all ASCII characters with some classification;+ - As a function that tests whether a particular character belongs to the classification.++Each list contains exactly the characters for which its corresponding predicate is true.++>>> controlCodes == filter isControl all+True++>>> printableCharacters == filter isPrint all+True++>>> letters == filter isLetter all+True++>>> capitalLetters == filter isUpper all+True++>>> smallLetters == filter isLower all+True++>>> digits == filter isDigit all+True++>>> numbers == filter isNumber all+True++>>> octDigits == filter isOctDigit all+True++>>> hexDigits == filter isHexDigit all+True++-}
+ library/ASCII/Predicates.hs view
@@ -0,0 +1,271 @@+module ASCII.Predicates+ (+ {- * Group predicates -} isControl, isPrint,+ {- * Case predicates -} isLower, isUpper,+ {- * Letter predicates -} isLetter, isAlpha,+ {- * Number predicates -} isDigit, isOctDigit, isHexDigit, isNumber,+ {- * Miscellaneous predicates -} isSpace, isAlphaNum, isMark, isPunctuation, isSymbol, isSeparator+ {- * Notes -} {- $notes -}+ )+ where++import ASCII.Char ( Char (..) )+import Data.Bool ( Bool (..), otherwise )+import Data.Eq ( (==) )+import Data.Function ( (.) )+import Data.Ord ( (<), (<=), (>=) )++import qualified ASCII.Char as Char+import qualified Data.Bool as Bool+import qualified Data.List as List++{- | Returns True for control characters.++This function is analogous to 'Data.Char.isControl' in the "Data.Char" module.++-}++isControl :: Char -> Bool+isControl x =+ case x of+ _ | (x < Char.Space) -> True+ Char.Delete -> True+ _ -> False++{- | Returns True for printable characters.++This function is analogous to 'Data.Char.isPrint' in the "Data.Char" module.++-}++isPrint :: Char -> Bool+isPrint = Bool.not . isControl++{- | Returns True for lower-case letters, from 'SmallLetterA' to 'SmallLetterZ'.++This function is analogous to 'Data.Char.isLower' in the "Data.Char" module.++-}++isLower :: Char -> Bool+isLower x = (Bool.&&) (x >= SmallLetterA) (x <= SmallLetterZ)++{- | Returns True for upper-case letters, from 'CapitalLetterA' to 'CapitalLetterZ'.++This function is analogous to 'Data.Char.isUpper' in the "Data.Char" module.++-}++isUpper :: Char -> Bool+isUpper x = (Bool.&&) (x >= CapitalLetterA) (x <= CapitalLetterZ)++{- | Returns True for letters:++- 'SmallLetterA' to 'SmallLetterZ'+- 'CapitalLetterA' to 'CapitalLetterZ'++This function is analogous to 'Data.Char.isLetter' in the "Data.Char" module.++-}++isLetter :: Char -> Bool+isLetter x = (Bool.||) (isLower x) (isUpper x)++{- | Synonym for 'isLetter'.++This function is analogous to 'Data.Char.isAlpha' in the "Data.Char" module.++-}++isAlpha :: Char -> Bool+isAlpha = isLetter++{- | Returns True for the characters from 'Digit0' to 'Digit9'.++This function is analogous to 'Data.Char.isDigit' in the "Data.Char" module.++-}++isDigit :: Char -> Bool+isDigit x = (Bool.&&) (x >= Digit0) (x <= Digit9)++{- | Returns True for the characters from 'Digit0' to 'Digit7'.++This function is analogous to 'Data.Char.isOctDigit' in the "Data.Char" module.++-}++isOctDigit :: Char -> Bool+isOctDigit x = (Bool.&&) (x >= Digit0) (x <= Digit7)++{- | Returns True for characters in any of the following ranges:++- 'Digit0' to 'Digit9'+- 'CapitalLetterA' to 'CapitalLetterF'+- 'SmallLetterA' to 'SmallLetterF'++This function is analogous to 'Data.Char.isHexDigit' in the "Data.Char" module.++-}++isHexDigit :: Char -> Bool+isHexDigit x | isDigit x = True+ | (Bool.&&) (x >= CapitalLetterA) (x <= CapitalLetterF) = True+ | (Bool.&&) (x >= SmallLetterA) (x <= SmallLetterF) = True+ | otherwise = False++{- | Synonym for 'isDigit'.++In the "Data.Char" module, 'Data.Char.isDigit' selects only the ASCII digits 0 through 9, and 'Data.Char.isNumber' selects a wider set of characters because the full Unicode character set contains more numeric characters than just the ASCII digits. In this module, these two functions are redundant, but we include this synonym for compatibility with "Data.Char".++-}++isNumber :: Char -> Bool+isNumber = isDigit++{- | Returns True for the following characters:++- 'Space'+- 'HorizontalTab'+- 'LineFeed'+- 'VerticalTab'+- 'FormFeed'+- 'CarriageReturn'++This function is analogous to 'Data.Char.isSpace' in the "Data.Char" module.++-}++isSpace :: Char -> Bool+isSpace Space = True+isSpace x = (Bool.&&) (x >= HorizontalTab) (x <= CarriageReturn)++-- | This function is analogous to 'Data.Char.isAlphaNum' in the "Data.Char" module.++isAlphaNum :: Char -> Bool+isAlphaNum x = (Bool.||) (isAlpha x) (isDigit x)++-- | Selects mark characters, for example accents and the like, which combine with preceding characters. This always returns False because ASCII does not include any mark characters. This function is included only for compatibility with 'Data.Char.isMark' in the "Data.Char" module.++isMark :: Char -> Bool+isMark _ = False++{- | Returns True for the following characters:++- 'ExclamationMark'+- 'QuotationMark'+- 'NumberSign'+- 'PercentSign'+- 'Ampersand'+- 'Apostrophe'+- 'LeftParenthesis'+- 'RightParenthesis'+- 'Asterisk'+- 'Comma'+- 'HyphenMinus'+- 'FullStop'+- 'Slash'+- 'Colon'+- 'Semicolon'+- 'QuestionMark'+- 'AtSign'+- 'LeftSquareBracket'+- 'Backslash'+- 'RightSquareBracket'+- 'Underscore'+- 'LeftCurlyBracket'+- 'RightCurlyBracket'++This function is analogous to 'Data.Char.isPunctuation' in the "Data.Char" module.++-}++isPunctuation :: Char -> Bool+isPunctuation = (`List.elem` [ExclamationMark, QuotationMark, NumberSign, PercentSign, Ampersand, Apostrophe, LeftParenthesis, RightParenthesis, Asterisk, Comma, HyphenMinus, FullStop, Slash, Colon, Semicolon, QuestionMark, AtSign, LeftSquareBracket, Backslash, RightSquareBracket, Underscore, LeftCurlyBracket, RightCurlyBracket])++{- | Returns True for the following characters:++- 'DollarSign'+- 'PlusSign'+- 'LessThanSign'+- 'EqualsSign'+- 'GreaterThanSign'+- 'Caret'+- 'GraveAccent'+- 'VerticalLine'+- 'Tilde'++This function is analogous to 'Data.Char.isSymbol' in the "Data.Char" module.++-}++isSymbol :: Char -> Bool+isSymbol = (`List.elem` [DollarSign, PlusSign, LessThanSign, EqualsSign, GreaterThanSign, Caret, GraveAccent, VerticalLine, Tilde])++{- | Returns True if the character is 'Space'.++This function is analogous to 'Data.Char.isSeparator' in the "Data.Char" module.++-}++isSeparator :: Char -> Bool+isSeparator = (== Space)++{- $notes++This module defines drop-in replacements for closely related definitions of the same name in the "Data.Char" module.++>>> import qualified Data.Char+>>> import qualified Data.List+>>> convert = Data.Char.chr . ASCII.Char.toInt+>>> eq f g = Data.List.all (\x -> f x == g (convert x)) ASCII.Char.allCharacters++>>> eq isControl Data.Char.isControl+True++>>> eq isSpace Data.Char.isSpace+True++>>> eq isLower Data.Char.isLower+True++>>> eq isUpper Data.Char.isUpper+True++>>> eq isAlpha Data.Char.isAlpha+True++>>> eq isAlphaNum Data.Char.isAlphaNum+True++>>> eq isPrint Data.Char.isPrint+True++>>> eq isDigit Data.Char.isDigit+True++>>> eq isOctDigit Data.Char.isOctDigit+True++>>> eq isHexDigit Data.Char.isHexDigit+True++>>> eq isLetter Data.Char.isLetter+True++>>> eq isMark Data.Char.isMark+True++>>> eq isNumber Data.Char.isNumber+True++>>> eq isPunctuation Data.Char.isPunctuation+True++>>> eq isSymbol Data.Char.isSymbol+True++>>> eq isSeparator Data.Char.isSeparator+True++-}
+ test/test.hs view
@@ -0,0 +1,89 @@+module Main where++import ASCII.ListsAndPredicates++import qualified ASCII.Char++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.List (filter, intercalate, map, null)+import Data.Semigroup ((<>))+import Numeric.Natural (Natural)+import System.Exit (die)+import System.IO (IO, putStrLn)+import Text.Show (show)++import qualified Data.Char as Char+import qualified Data.List as List++main :: IO ()+main = dieIfFailures $ do++ do+ let lists = [ all, printableCharacters, controlCodes, letters,+ capitalLetters, smallLetters, digits, octDigits,+ hexDigits, numbers]++ test 1 $ List.all (\xs -> List.sort xs == xs) lists++ do+ let convert = Char.chr . ASCII.Char.toInt+ eq f g = List.all (\x -> f x == g (convert x))+ ASCII.Char.allCharacters++ test 2 $ eq isControl Char.isControl+ test 3 $ eq isSpace Char.isSpace+ test 4 $ eq isLower Char.isLower+ test 5 $ eq isUpper Char.isUpper+ test 6 $ eq isAlpha Char.isAlpha+ test 7 $ eq isAlphaNum Char.isAlphaNum+ test 8 $ eq isPrint Char.isPrint+ test 9 $ eq isDigit Char.isDigit+ test 10 $ eq isOctDigit Char.isOctDigit+ test 11 $ eq isHexDigit Char.isHexDigit+ test 12 $ eq isLetter Char.isLetter+ test 13 $ eq isMark Char.isMark+ test 14 $ eq isNumber Char.isNumber+ test 15 $ eq isPunctuation Char.isPunctuation+ test 16 $ eq isSymbol Char.isSymbol+ test 17 $ eq isSeparator Char.isSeparator++ test 18 $ controlCodes == filter isControl all+ test 19 $ printableCharacters == filter isPrint all+ test 20 $ letters == filter isLetter all+ test 21 $ capitalLetters == filter isUpper all+ test 22 $ smallLetters == filter isLower all+ test 23 $ digits == filter isDigit all+ test 24 $ numbers == filter isNumber all+ test 25 $ octDigits == filter isOctDigit all+ test 26 $ hexDigits == filter isHexDigit all++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