packages feed

ascii-superset 1.2.1.0 → 1.2.2.0

raw patch · 5 files changed

+109/−73 lines, 5 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ ASCII.CaseRefinement: instance ASCII.Superset.CharSuperset char => ASCII.Superset.ToChar (ASCII.CaseRefinement.ASCII'case letterCase char)
+ ASCII.CaseRefinement: instance ASCII.Superset.ToCaselessChar char => ASCII.Superset.ToCaselessChar (ASCII.CaseRefinement.ASCII'case letterCase char)
+ ASCII.CaseRefinement: instance ASCII.Superset.ToCaselessString string => ASCII.Superset.ToCaselessString (ASCII.CaseRefinement.ASCII'case letterCase string)
+ ASCII.CaseRefinement: instance ASCII.Superset.ToString string => ASCII.Superset.ToString (ASCII.CaseRefinement.ASCII'case letterCase string)

Files

ascii-superset.cabal view
@@ -1,7 +1,7 @@ cabal-version: 3.0  name: ascii-superset-version: 1.2.1.0+version: 1.2.2.0 synopsis: Representing ASCII with refined supersets category: Data, Text @@ -46,7 +46,7 @@         TypeApplications      build-depends:-        ascii-case ^>= 1.0.1+      , ascii-case ^>= 1.0.1       , ascii-caseless ^>= 0.0.0       , ascii-char ^>= 1.0       , base ^>= 4.14 || ^>= 4.15 || ^>= 4.16 || ^>= 4.17@@ -65,7 +65,7 @@         StandaloneDeriving      build-depends:-        bytestring ^>= 0.10.12 || ^>= 0.11+      , bytestring ^>= 0.10.12 || ^>= 0.11       , hashable ^>= 1.3.5 || ^>= 1.4      exposed-modules:@@ -87,5 +87,5 @@         TemplateHaskell      build-depends:-        ascii-superset+      , ascii-superset       , hspec ^>= 2.8.5 || ^>= 2.9 || ^>= 2.10
changelog.md view
@@ -1,3 +1,12 @@+### 1.2.2.0 (2023-01-05)++`ASCII'case` now has instances for:++* `ToCaselessChar`+* `ToChar`+* `ToCaselessString`+* `ToString`+ ### 1.2.1.0 (2023-01-05)  Add `instance FromChar CaselessChar`
library/ASCII/CaseRefinement.hs view
@@ -18,7 +18,7 @@ import qualified ASCII.Case as Case import qualified ASCII.Caseless as Caseless import qualified ASCII.Char as ASCII-import qualified ASCII.Superset as Superset+import qualified ASCII.Superset as S import {-# source #-} qualified ASCII.Refinement as Refinement  import Control.Monad (guard)@@ -40,9 +40,9 @@ import qualified Data.Bool as Bool import qualified Data.List as List -{- | This type constructor indicates that a value from some ASCII superset is-valid ASCII, and also that any letters belong to a particular 'Case' indicated-by the @letterCase@ type parameter.+{-| Indicates that a value from some ASCII superset is valid ASCII, and also+    that any letters belong to a particular 'Case' indicated by the @letterCase@+    type parameter  The @superset@ type parameter is the ASCII superset, which should be a type with an instance of either 'CharSuperset' or 'StringSuperset'.@@ -84,8 +84,26 @@      showList x = showString "asciiCaseUnsafe " . showList (List.map lift x) +instance S.ToCaselessChar char => S.ToCaselessChar (ASCII'case letterCase char) where+    isAsciiCaselessChar _ = Bool.True+    toCaselessCharUnsafe = S.toCaselessCharUnsafe . lift++instance S.CharSuperset char => S.ToChar (ASCII'case letterCase char) where+    isAsciiChar _ = Bool.True+    toCharUnsafe = S.toCharUnsafe . lift++instance S.ToCaselessString string => S.ToCaselessString (ASCII'case letterCase string) where+    isAsciiCaselessString _ = Bool.True+    toCaselessCharListUnsafe = S.toCaselessCharListUnsafe . lift+    toCaselessCharListSub = S.toCaselessCharListSub . lift++instance S.ToString string => S.ToString (ASCII'case letterCase string) where+    isAsciiString _ = Bool.True+    toCharListUnsafe = S.toCharListUnsafe . lift+    toCharListSub = S.toCharListUnsafe . lift+ {-| Change the type of an ASCII superset value that is known to be valid ASCII where-letters are restricted to the 'Case' designated by the @letterCase@ type variable.+    letters are restricted to the 'Case' designated by the @letterCase@ type variable  This is "unsafe" because this assertion is unchecked, so this function is capable of producing an invalid 'ASCII'case' value. -}@@ -97,10 +115,7 @@ {- $aliases  The 'ASCII'upper' and 'ASCII'lower' type aliases exist primarily so that you can-use 'ASCII'case' without the DataKinds language extension.---}-+use 'ASCII'case' without the DataKinds language extension. -} type ASCII'upper superset = ASCII'case 'UpperCase superset  type ASCII'lower superset = ASCII'case 'LowerCase superset@@ -114,104 +129,104 @@ ---  {-| Return 'Just' an 'ASCII'case' character if the input is an ASCII character-in the proper case, or 'Nothing' otherwise -}+    in the proper case, or 'Nothing' otherwise -} validateChar :: forall letterCase superset. KnownCase letterCase => CharSuperset superset =>     superset {- ^ Character which may or may not be in the ASCII character set;                   if a letter, may be in any case -}     -> Maybe (ASCII'case letterCase superset) validateChar x = do-    c <- Superset.toCharMaybe x+    c <- S.toCharMaybe x     guard (Bool.not (Case.isCase (Case.opposite (theCase @letterCase)) c))     Just (asciiCaseUnsafe x) -{- | Return an 'ASCII'case' character if the input is an ASCII character in the-proper case, or 'ASCII.Substitute' otherwise -}+{-| Return an 'ASCII'case' character if the input is an ASCII character in the+    proper case, or 'ASCII.Substitute' otherwise -} substituteChar :: forall letterCase superset. KnownCase letterCase => CharSuperset superset =>     superset     -> ASCII'case letterCase superset substituteChar x = case validateChar x of-    Nothing -> asciiCaseUnsafe (Superset.fromChar ASCII.Substitute)+    Nothing -> asciiCaseUnsafe (S.fromChar ASCII.Substitute)     Just c -> c  {-| Lift a 'CaselessChar' into a superset type, wrapped in the 'ASCII'case'-refinement to save the evidence that it is ASCII in a particular case -}+    refinement to save the evidence that it is ASCII in a particular case -} fromCaselessChar :: forall letterCase superset. KnownCase letterCase => CharSuperset superset =>     CaselessChar -- ^ Character which, if it is a letter, does not have a specified case     -> ASCII'case letterCase superset-fromCaselessChar = asciiCaseUnsafe . Superset.fromChar . Caseless.toCase (theCase @letterCase)+fromCaselessChar = asciiCaseUnsafe . S.fromChar . Caseless.toCase (theCase @letterCase)  {-| Given a character from some type that is known to represent an ASCII-character in a particular case, obtain the caseless ASCII character it-represents -}+    character in a particular case, obtain the caseless ASCII character+    it represents -} toCaselessChar :: CharSuperset superset =>     ASCII'case letterCase superset {- ^ Character that is known to be ASCII, and                                         in the particular case if it is a letter -}     -> CaselessChar-toCaselessChar = Caseless.disregardCase . Superset.toCharUnsafe . lift+toCaselessChar = Caseless.disregardCase . S.toCharUnsafe . lift  {-| Given a character from a larger set that is known to represent an ASCII-character, manipulate it as if it were an ASCII character -}+    character, manipulate it as if it were an ASCII character -} asCaselessChar :: forall letterCase superset. KnownCase letterCase => CharSuperset superset =>     (CaselessChar -> CaselessChar) -- ^ Case-insensitive function over ASCII characters     -> ASCII'case letterCase superset {- ^ Character that is known to be ASCII, and                                            in the particular case if it is a letter -}     -> ASCII'case letterCase superset-asCaselessChar f = asciiCaseUnsafe . Superset.asCharUnsafe g . lift+asCaselessChar f = asciiCaseUnsafe . S.asCharUnsafe g . lift   where     g = Caseless.toCase (theCase @letterCase) . f . Caseless.assumeCaseUnsafe (theCase @letterCase)  {-| Given an ASCII superset character that is known to be valid ASCII,-refine it further by converting it to a particular letter case -}+    refine it further by converting it to a particular letter case -} refineCharToCase :: forall letterCase char. KnownCase letterCase => CharSuperset char =>     ASCII char -> ASCII'case letterCase char-refineCharToCase = asciiCaseUnsafe . Superset.toCaseChar (theCase @letterCase) . Refinement.lift+refineCharToCase = asciiCaseUnsafe . S.toCaseChar (theCase @letterCase) . Refinement.lift  ---  {-| Return 'Just' an 'ASCII'case' string if the input consists entirely of ASCII-characters in the proper case, or 'Nothing' otherwise -}+    characters in the proper case, or 'Nothing' otherwise -} validateString :: forall letterCase superset. KnownCase letterCase => StringSuperset superset =>     superset -- ^ String which may or may not be valid ASCII, where letters may be in any case     -> Maybe (ASCII'case letterCase superset) validateString x = do-    s <- Superset.toCharListMaybe x+    s <- S.toCharListMaybe x     guard (Bool.not (any (Case.isCase (Case.opposite (theCase @letterCase))) s))     Just (asciiCaseUnsafe x)  {-| Lift a list of 'CaselessChar' into a superset string type, wrapped in the-'ASCII'case' refinement to save the evidence that all of the characters in the-string are ASCII in a particular case. -}+    'ASCII'case' refinement to save the evidence that all of the characters in+    the string are ASCII in a particular case -} fromCaselessCharList :: forall letterCase superset. KnownCase letterCase => StringSuperset superset =>     [CaselessChar] -- ^ Case-insensitive ASCII string represented as a list of caseless characters     -> ASCII'case letterCase superset-fromCaselessCharList = asciiCaseUnsafe . Superset.fromCharList . List.map (Caseless.toCase (theCase @letterCase))+fromCaselessCharList = asciiCaseUnsafe . S.fromCharList . List.map (Caseless.toCase (theCase @letterCase)) -{-| Given a string from some type that is known to represent only ASCII-characters in a particular case, obtain the caseless characters it represents -}+{-| Given a string from some type that is known to represent only ASCII characters+    in a particular case, obtain the caseless characters it represents -} toCaselessCharList :: forall letterCase superset. KnownCase letterCase => StringSuperset superset =>     ASCII'case letterCase superset -- ^ String that is known to be valid ASCII in a particular case     -> [CaselessChar]-toCaselessCharList = List.map (Caseless.assumeCaseUnsafe (theCase @letterCase)) . Superset.toCharListUnsafe . lift+toCaselessCharList = List.map (Caseless.assumeCaseUnsafe (theCase @letterCase)) . S.toCharListUnsafe . lift  {-| Forces a string from a larger character set into cased ASCII by using the-'ASCII.Substitute' character in place of any unacceptable characters. -}+    'ASCII.Substitute' character in place of any unacceptable characters -} substituteString :: forall letterCase superset. KnownCase letterCase => StringSuperset superset =>     superset -- ^ String which may or may not be valid ASCII, where letters may be in any case     -> ASCII'case letterCase superset-substituteString = asciiCaseUnsafe . Superset.fromCharList . List.map f . Superset.toCharListSub+substituteString = asciiCaseUnsafe . S.fromCharList . List.map f . S.toCharListSub   where     f x = if Case.isCase (Case.opposite (theCase @letterCase)) x           then ASCII.Substitute           else x  {-| Given a string from a larger set that is known to consist entirely of ASCII-characters in a particular case, map over the characters in the string as if-they were caseless ASCII characters -}+    characters in a particular case, map over the characters in the string as if+    they were caseless ASCII characters -} mapChars :: forall letterCase superset. KnownCase letterCase => StringSuperset superset =>     (CaselessChar -> CaselessChar) -- ^ Case-insensitive function over ASCII characters     -> ASCII'case letterCase superset -- ^ String that is known to be valid ASCII in a particular case     -> ASCII'case letterCase superset-mapChars f = asciiCaseUnsafe . Superset.mapCharsUnsafe g . lift+mapChars f = asciiCaseUnsafe . S.mapCharsUnsafe g . lift   where     g = Caseless.toCase (theCase @letterCase) . f . Caseless.assumeCaseUnsafe (theCase @letterCase) @@ -219,4 +234,4 @@ refine it further by converting it to a particular letter case -} refineStringToCase :: forall letterCase char. KnownCase letterCase => StringSuperset char =>     ASCII char -> ASCII'case letterCase char-refineStringToCase = asciiCaseUnsafe . Superset.toCaseString (theCase @letterCase) . Refinement.lift+refineStringToCase = asciiCaseUnsafe . S.toCaseString (theCase @letterCase) . Refinement.lift
library/ASCII/Lift.hs view
@@ -1,3 +1,10 @@+{-|++@+(lift CapitalLetterA :: Word8) == 65++(lift [CapitalLetterH, SmallLetterI, ExclamationMark] :: Text) == "Hi!"+@ -} module ASCII.Lift (Lift (..)) where  import ASCII.Case (Case (..))@@ -6,11 +13,12 @@ import ASCII.Refinement (ASCII) import ASCII.Superset (CharSuperset, StringSuperset) -import qualified ASCII.Refinement as Refinement-import qualified ASCII.Superset as Superset import qualified ASCII.CaseRefinement as CaseRefinement+import qualified ASCII.Refinement as Refinement+import qualified ASCII.Superset as S  import qualified Prelude+ import Data.Function ((.))  {-| Embedding of one character set within another@@ -19,13 +27,7 @@ ASCII, some subset of ASCII, or some superset of ASCII. -} class Lift subset superset where -    {-| Converts from a smaller to a larger type.--    >>> lift CapitalLetterA :: Word8-    65--    >>> lift [CapitalLetterH,SmallLetterI,ExclamationMark] :: Text-    "Hi!"+    {-| Converts from a smaller to a larger type      Due to the highly polymorphic nature of the 'lift' function,     often it must used with an explicit type signature or type@@ -43,9 +45,9 @@ {-| An ASCII 'Char' may be 'lift'ed into any larger character set (a 'CharSuperset'); for example, 'lift' can convert an ASCII character into a value of the standard 'Prelude.Char' type in "Prelude". -}-instance CharSuperset superset => Lift Char superset where lift = Superset.fromChar+instance CharSuperset superset => Lift Char superset where lift = S.fromChar  {-| An ASCII 'Char' list may be 'lift'ed into a string of any larger character set (a 'StringSuperset'); for example, 'lift' can convert a list of ASCII characters into a value of the standard 'Prelude.String' type in "Prelude". -}-instance StringSuperset superset => Lift [Char] superset where lift = Superset.fromCharList+instance StringSuperset superset => Lift [Char] superset where lift = S.fromCharList
library/ASCII/Refinement.hs view
@@ -26,10 +26,12 @@ 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'.+{-| This type constructor indicates that a value from some ASCII superset+    is valid ASCII +The type parameter is the ASCII superset, which should be a type with an+instance of either 'CharSuperset' or 'StringSuperset'.+ For example, whereas a 'Data.Text.Text' value may contain a combination of ASCII and non-ASCII characters, a value of type @'ASCII' 'Data.Text.Text'@ may contain only ASCII characters. -}@@ -102,9 +104,11 @@ asciiUnsafe = ASCII_Unsafe  {-|->>> map validateChar [-1, 65, 97, 128] :: [Maybe (ASCII Int)]-[Nothing,Just (asciiUnsafe 65),Just (asciiUnsafe 97),Nothing]--}++@+(map validateChar [-1, 65, 97, 128] :: [Maybe (ASCII Int)])+    == [Nothing, Just (asciiUnsafe 65), Just (asciiUnsafe 97), Nothing]+@ -} validateChar :: S.CharSuperset superset => superset -> Maybe (ASCII superset) validateChar x = if S.isAsciiChar x then Just (asciiUnsafe x) else Nothing @@ -118,35 +122,41 @@ toChar = S.toCharUnsafe . lift  {-|->>> fromCharList [CapitalLetterH,SmallLetterI,ExclamationMark] :: ASCII Text-asciiUnsafe "Hi!"--}++@+fromCharList [CapitalLetterH, SmallLetterI, ExclamationMark]+    == (asciiUnsafe "Hi!" :: ASCII Text)+@ -} fromCharList :: S.StringSuperset superset => [ASCII.Char] -> ASCII superset fromCharList = asciiUnsafe . S.fromCharList  {-|->>> toCharList (substituteString "Piñata" :: ASCII Text)-[CapitalLetterP,SmallLetterI,Substitute,SmallLetterA,SmallLetterT,SmallLetterA]--}++@+toCharList (substituteString \"Piñata" :: ASCII Text) ==+    [CapitalLetterP, SmallLetterI, Substitute, SmallLetterA, SmallLetterT, SmallLetterA]+@ -} toCharList :: S.StringSuperset superset => ASCII superset -> [ASCII.Char] toCharList = S.toCharListUnsafe . lift  {-| Forces a string from a larger character set into ASCII by using the-'ASCII.Substitute' character in place of any non-ASCII characters+    'ASCII.Substitute' character in place of any non-ASCII characters ->>> substituteString "Cristóbal" :: ASCII Text-asciiUnsafe "Crist\SUBbal"--}+@+(substituteString \"Cristóbal" :: ASCII Text) == asciiUnsafe "Crist\SUBbal"+@ -} substituteString :: S.StringSuperset superset => superset -> ASCII superset substituteString = asciiUnsafe . S.substituteString  {-|->>> map validateString ["Hello", "Cristóbal"] :: [Maybe (ASCII Text)]-[Just (asciiUnsafe "Hello"),Nothing] ->>> map validateString ["Hello", "Cristóbal"] :: [Maybe (ASCII String)]-[Just (asciiUnsafe "Hello"),Nothing]--}+@+(map validateString [\"Hello", \"Cristóbal"] :: [Maybe (ASCII Text)])+    == [Just (asciiUnsafe \"Hello"), Nothing]++(map validateString [\"Hello", \"Cristóbal"] :: [Maybe (ASCII String)])+    == [Just (asciiUnsafe \"Hello"), Nothing]+@ -} validateString :: S.StringSuperset superset => superset -> Maybe (ASCII superset) validateString x = if S.isAsciiString x then Just (asciiUnsafe x) else Nothing