ascii-numbers 1.0.0.0 → 1.1.0.0
raw patch · 5 files changed
+221/−158 lines, 5 filesdep −d10dep ~basedep ~hedgehogdep ~textPVP ok
version bump matches the API change (PVP)
Dependencies removed: d10
Dependency ranges changed: base, hedgehog, text
API changes (from Hackage documentation)
- ASCII.Decimal: D0 :: D10
- ASCII.Decimal: D1 :: D10
- ASCII.Decimal: D2 :: D10
- ASCII.Decimal: D3 :: D10
- ASCII.Decimal: D4 :: D10
- ASCII.Decimal: D5 :: D10
- ASCII.Decimal: D6 :: D10
- ASCII.Decimal: D7 :: D10
- ASCII.Decimal: D8 :: D10
- ASCII.Decimal: D9 :: D10
- ASCII.Decimal: data D10
- ASCII.Decimal: instance ASCII.Decimal.DigitStringSuperset [D10.Safe.Type.D10]
- ASCII.Decimal: instance ASCII.Decimal.DigitSuperset D10.Safe.Type.D10
- ASCII.Hexadecimal: D0 :: D16
- ASCII.Hexadecimal: D1 :: D16
- ASCII.Hexadecimal: D10 :: D16
- ASCII.Hexadecimal: D11 :: D16
- ASCII.Hexadecimal: D12 :: D16
- ASCII.Hexadecimal: D13 :: D16
- ASCII.Hexadecimal: D14 :: D16
- ASCII.Hexadecimal: D15 :: D16
- ASCII.Hexadecimal: D2 :: D16
- ASCII.Hexadecimal: D3 :: D16
- ASCII.Hexadecimal: D4 :: D16
- ASCII.Hexadecimal: D5 :: D16
- ASCII.Hexadecimal: D6 :: D16
- ASCII.Hexadecimal: D7 :: D16
- ASCII.Hexadecimal: D8 :: D16
- ASCII.Hexadecimal: D9 :: D16
- ASCII.Hexadecimal: data D16
- ASCII.Hexadecimal: instance Data.Data.Data ASCII.Hexadecimal.D16
- ASCII.Hexadecimal: instance Data.Hashable.Class.Hashable ASCII.Hexadecimal.D16
- ASCII.Hexadecimal: instance GHC.Classes.Eq ASCII.Hexadecimal.D16
- ASCII.Hexadecimal: instance GHC.Classes.Ord ASCII.Hexadecimal.D16
- ASCII.Hexadecimal: instance GHC.Enum.Bounded ASCII.Hexadecimal.D16
- ASCII.Hexadecimal: instance GHC.Enum.Enum ASCII.Hexadecimal.D16
- ASCII.Hexadecimal: instance GHC.Generics.Generic ASCII.Hexadecimal.D16
- ASCII.Hexadecimal: instance GHC.Show.Show ASCII.Hexadecimal.D16
+ ASCII.Decimal: Digit0 :: Digit
+ ASCII.Decimal: Digit1 :: Digit
+ ASCII.Decimal: Digit2 :: Digit
+ ASCII.Decimal: Digit3 :: Digit
+ ASCII.Decimal: Digit4 :: Digit
+ ASCII.Decimal: Digit5 :: Digit
+ ASCII.Decimal: Digit6 :: Digit
+ ASCII.Decimal: Digit7 :: Digit
+ ASCII.Decimal: Digit8 :: Digit
+ ASCII.Decimal: Digit9 :: Digit
+ ASCII.Decimal: data Digit
+ ASCII.Decimal: instance ASCII.Decimal.DigitStringSuperset [ASCII.Decimal.Digit]
+ ASCII.Decimal: instance ASCII.Decimal.DigitStringSuperset string => ASCII.Lift.Lift [ASCII.Decimal.Digit] string
+ ASCII.Decimal: instance ASCII.Decimal.DigitSuperset ASCII.Decimal.Digit
+ ASCII.Decimal: instance ASCII.Decimal.DigitSuperset char => ASCII.Lift.Lift ASCII.Decimal.Digit char
+ ASCII.Decimal: instance Data.Data.Data ASCII.Decimal.Digit
+ ASCII.Decimal: instance Data.Hashable.Class.Hashable ASCII.Decimal.Digit
+ ASCII.Decimal: instance GHC.Classes.Eq ASCII.Decimal.Digit
+ ASCII.Decimal: instance GHC.Classes.Ord ASCII.Decimal.Digit
+ ASCII.Decimal: instance GHC.Enum.Bounded ASCII.Decimal.Digit
+ ASCII.Decimal: instance GHC.Enum.Enum ASCII.Decimal.Digit
+ ASCII.Decimal: instance GHC.Generics.Generic ASCII.Decimal.Digit
+ ASCII.Decimal: instance GHC.Show.Show ASCII.Decimal.Digit
+ ASCII.Hexadecimal: instance ASCII.Hexadecimal.HexCharSuperset char => ASCII.Lift.Lift ASCII.Hexadecimal.HexChar char
+ ASCII.Hexadecimal: instance ASCII.Hexadecimal.HexStringSuperset string => ASCII.Lift.Lift [ASCII.Hexadecimal.HexChar] string
+ ASCII.Word4: Number0 :: Word4
+ ASCII.Word4: Number1 :: Word4
+ ASCII.Word4: Number10 :: Word4
+ ASCII.Word4: Number11 :: Word4
+ ASCII.Word4: Number12 :: Word4
+ ASCII.Word4: Number13 :: Word4
+ ASCII.Word4: Number14 :: Word4
+ ASCII.Word4: Number15 :: Word4
+ ASCII.Word4: Number2 :: Word4
+ ASCII.Word4: Number3 :: Word4
+ ASCII.Word4: Number4 :: Word4
+ ASCII.Word4: Number5 :: Word4
+ ASCII.Word4: Number6 :: Word4
+ ASCII.Word4: Number7 :: Word4
+ ASCII.Word4: Number8 :: Word4
+ ASCII.Word4: Number9 :: Word4
+ ASCII.Word4: data Word4
+ ASCII.Word4: instance Data.Data.Data ASCII.Word4.Word4
+ ASCII.Word4: instance Data.Hashable.Class.Hashable ASCII.Word4.Word4
+ ASCII.Word4: instance GHC.Classes.Eq ASCII.Word4.Word4
+ ASCII.Word4: instance GHC.Classes.Ord ASCII.Word4.Word4
+ ASCII.Word4: instance GHC.Enum.Bounded ASCII.Word4.Word4
+ ASCII.Word4: instance GHC.Enum.Enum ASCII.Word4.Word4
+ ASCII.Word4: instance GHC.Generics.Generic ASCII.Word4.Word4
+ ASCII.Word4: instance GHC.Show.Show ASCII.Word4.Word4
- ASCII.Decimal: digitInteger :: D10 -> Integer
+ ASCII.Decimal: digitInteger :: Digit -> Integer
- ASCII.Decimal: digitNatural :: D10 -> Natural
+ ASCII.Decimal: digitNatural :: Digit -> Natural
- ASCII.Decimal: fromDigit :: DigitSuperset char => D10 -> char
+ ASCII.Decimal: fromDigit :: DigitSuperset char => Digit -> char
- ASCII.Decimal: fromDigitList :: DigitStringSuperset string => [D10] -> string
+ ASCII.Decimal: fromDigitList :: DigitStringSuperset string => [Digit] -> string
- ASCII.Decimal: integerDigitMaybe :: Integer -> Maybe D10
+ ASCII.Decimal: integerDigitMaybe :: Integer -> Maybe Digit
- ASCII.Decimal: naturalDigitMaybe :: Natural -> Maybe D10
+ ASCII.Decimal: naturalDigitMaybe :: Natural -> Maybe Digit
- ASCII.Decimal: toDigitListMaybe :: DigitStringSuperset string => string -> Maybe [D10]
+ ASCII.Decimal: toDigitListMaybe :: DigitStringSuperset string => string -> Maybe [Digit]
- ASCII.Decimal: toDigitListUnsafe :: DigitStringSuperset string => string -> [D10]
+ ASCII.Decimal: toDigitListUnsafe :: DigitStringSuperset string => string -> [Digit]
- ASCII.Decimal: toDigitMaybe :: DigitSuperset char => char -> Maybe D10
+ ASCII.Decimal: toDigitMaybe :: DigitSuperset char => char -> Maybe Digit
- ASCII.Decimal: toDigitUnsafe :: DigitSuperset char => char -> D10
+ ASCII.Decimal: toDigitUnsafe :: DigitSuperset char => char -> Digit
- ASCII.Hexadecimal: HexDigit :: D10 -> HexCharBreakdown
+ ASCII.Hexadecimal: HexDigit :: Digit -> HexCharBreakdown
- ASCII.Hexadecimal: d16HexChar :: Case -> D16 -> HexChar
+ ASCII.Hexadecimal: d16HexChar :: Case -> Word4 -> HexChar
- ASCII.Hexadecimal: d16HexLetter :: D16 -> Maybe HexLetter
+ ASCII.Hexadecimal: d16HexLetter :: Word4 -> Maybe HexLetter
- ASCII.Hexadecimal: d16Integer :: D16 -> Integer
+ ASCII.Hexadecimal: d16Integer :: Word4 -> Integer
- ASCII.Hexadecimal: d16Natural :: D16 -> Natural
+ ASCII.Hexadecimal: d16Natural :: Word4 -> Natural
- ASCII.Hexadecimal: hexCharD16 :: HexChar -> D16
+ ASCII.Hexadecimal: hexCharD16 :: HexChar -> Word4
- ASCII.Hexadecimal: hexLetterD16 :: HexLetter -> D16
+ ASCII.Hexadecimal: hexLetterD16 :: HexLetter -> Word4
- ASCII.Hexadecimal: integerD16Maybe :: Integer -> Maybe D16
+ ASCII.Hexadecimal: integerD16Maybe :: Integer -> Maybe Word4
- ASCII.Hexadecimal: integerD16Unsafe :: Integer -> D16
+ ASCII.Hexadecimal: integerD16Unsafe :: Integer -> Word4
- ASCII.Hexadecimal: naturalD16Maybe :: Natural -> Maybe D16
+ ASCII.Hexadecimal: naturalD16Maybe :: Natural -> Maybe Word4
- ASCII.Hexadecimal: naturalD16Unsafe :: Natural -> D16
+ ASCII.Hexadecimal: naturalD16Unsafe :: Natural -> Word4
Files
- ascii-numbers.cabal +3/−2
- library/ASCII/Decimal.hs +71/−34
- library/ASCII/Hexadecimal.hs +39/−45
- library/ASCII/Word4.hs +30/−0
- test/Main.hs +78/−77
ascii-numbers.cabal view
@@ -1,7 +1,7 @@ cabal-version: 3.0 name: ascii-numbers-version: 1.0.0.0+version: 1.1.0.0 synopsis: ASCII representations of numbers category: Data, Numeric, Text @@ -35,6 +35,7 @@ DerivingStrategies FlexibleInstances LambdaCase+ MultiParamTypeClasses NoImplicitPrelude StandaloneDeriving @@ -44,7 +45,6 @@ , ascii-superset ^>= 1.0.1 , base >= 4.13 && < 4.17 , bytestring ^>= 0.10 || ^>= 0.11- , d10 ^>= 1.0.1 , hashable >= 1.3 && < 1.5 , text ^>= 1.2.4 @@ -55,6 +55,7 @@ exposed-modules: ASCII.Decimal , ASCII.Hexadecimal+ , ASCII.Word4 other-modules: DList
library/ASCII/Decimal.hs view
@@ -5,7 +5,7 @@ {- ** Integer -} showInteger, readInteger, {- ** Integral -} showIntegral, readIntegral, - {- * The digit type -} D10 (..),+ {- * The digit type -} Digit (..), {- * Decimal digit superset classes -} {- ** Of digit -} DigitSuperset (..),@@ -18,24 +18,32 @@ ) where import qualified ASCII.Char as ASCII-import ASCII.Refinement (ASCII, asciiUnsafe, lift)+import qualified ASCII.Refinement+import ASCII.Lift (Lift (lift))+import ASCII.Refinement (ASCII, asciiUnsafe) import ASCII.Superset (StringSuperset, fromChar, fromCharList, toCharListMaybe, toCharMaybe) import Control.Monad ((<=<), (=<<)) import Data.Bifoldable (bifoldMap) import Data.Bits (Bits, toIntegralSized)-import Data.Bool (Bool, (&&))+import Data.Bool (Bool, (&&), (||))+import Data.Data (Data)+import Data.Eq (Eq) import Data.Function (id, (.)) import Data.Functor (fmap)+import Data.Hashable (Hashable) import Data.List.NonEmpty (NonEmpty, nonEmpty) import Data.Maybe (Maybe (..), fromJust, isJust) import Data.Monoid (mempty) import Data.Ord (Ord (..)) import Data.Word (Word8)+import GHC.Generics (Generic) import Numeric.Natural (Natural)-import Prelude (Integer, Integral, abs, fromEnum, fromInteger, fromIntegral,- negate, quotRem, toEnum, toInteger, (*), (+), (-))+import Prelude (Bounded (..), Enum (..), Integer, Integral, abs, fromEnum,+ fromInteger, fromIntegral, negate, quotRem, toEnum, toInteger,+ (*), (+), (-))+import Text.Show (Show) import qualified Data.Bool as Bool import qualified Data.Char as Unicode@@ -52,10 +60,28 @@ import DList (DList) import qualified DList -import D10.Safe (D10 (..))-import qualified D10.Safe as D10+{- | +The subset of ASCII used to represent unsigned decimal numbers: +* 'ASCII.Char.Digit0' to 'ASCII.Char.Digit9'++-}+data Digit+ = Digit0 -- ^ Zero+ | Digit1 -- ^ One+ | Digit2 -- ^ Two+ | Digit3 -- ^ Three+ | Digit4 -- ^ Four+ | Digit5 -- ^ Five+ | Digit6 -- ^ Six+ | Digit7 -- ^ Seven+ | Digit8 -- ^ Eight+ | Digit9 -- ^ Nine+ deriving stock (Bounded, Enum, Eq, Ord, Show, Data, Generic)+ deriving anyclass Hashable++ --- Show functions --- {- |@@ -69,13 +95,13 @@ showNatural :: DigitStringSuperset string => Natural -> string showNatural = \case- 0 -> fromDigitList [ D0 ]+ 0 -> fromDigitList [ Digit0 ] n -> fromDigitList (naturalList n) where- naturalList :: Natural -> [D10]+ naturalList :: Natural -> [Digit] naturalList = DList.toList . r where- r :: Natural -> DList D10+ r :: Natural -> DList Digit r = \case 0 -> mempty n ->@@ -136,7 +162,7 @@ readNatural :: DigitStringSuperset string => string -> Maybe Natural readNatural = (Just . readNaturalDigits) <=< nonEmpty <=< toDigitListMaybe where- readNaturalDigits :: NonEmpty D10 -> Natural+ readNaturalDigits :: NonEmpty Digit -> Natural readNaturalDigits = List.foldl' (\total x -> (10 * total) + fromIntegral (fromEnum x)) 0 {- |@@ -163,7 +189,7 @@ readNonNegative :: [ASCII.Char] -> Maybe Integer readNonNegative = (Just . toInteger . readIntegerDigits) <=< nonEmpty <=< toDigitListMaybe - readIntegerDigits :: NonEmpty D10 -> Integer+ readIntegerDigits :: NonEmpty Digit -> Integer readIntegerDigits = List.foldl' (\total x -> (10 * total) + fromIntegral (fromEnum x)) 0 {- |@@ -193,8 +219,8 @@ * @naturalDigitMaybe 12@ = @Nothing@ -}-naturalDigitMaybe :: Natural -> Maybe D10-naturalDigitMaybe = D10.natD10Maybe+naturalDigitMaybe :: Natural -> Maybe Digit+naturalDigitMaybe n = if n > 9 then Nothing else Just (toEnum (fromIntegral n)) {- | @@ -204,30 +230,41 @@ * @integerDigitMaybe 12@ = @Nothing@ -}-integerDigitMaybe :: Integer -> Maybe D10-integerDigitMaybe = D10.integerD10Maybe+integerDigitMaybe :: Integer -> Maybe Digit+integerDigitMaybe n = if (n < 0 || n > 9) then Nothing else Just (toEnum (fromInteger n)) -digitNatural :: D10 -> Natural-digitNatural = D10.d10Nat+digitNatural :: Digit -> Natural+digitNatural = fromIntegral . fromEnum -digitInteger :: D10 -> Integer-digitInteger = D10.d10Integer+digitInteger :: Digit -> Integer+digitInteger = fromIntegral . fromEnum +--- Lift instances ---++instance DigitSuperset char => Lift Digit char+ where+ lift = fromDigit++instance DigitStringSuperset string => Lift [Digit] string+ where+ lift = fromDigitList++ --- Classes --- class DigitSuperset char where - fromDigit :: D10 -> char+ fromDigit :: Digit -> char isDigit :: char -> Bool isDigit = isJust . toDigitMaybe - toDigitUnsafe :: char -> D10+ toDigitUnsafe :: char -> Digit toDigitUnsafe = fromJust . toDigitMaybe - toDigitMaybe :: char -> Maybe D10+ toDigitMaybe :: char -> Maybe Digit toDigitMaybe x = if isDigit x then Just (toDigitUnsafe x) else Nothing {-# minimal fromDigit, ((isDigit, toDigitUnsafe) | toDigitMaybe) #-}@@ -235,15 +272,15 @@ class DigitStringSuperset string where - fromDigitList :: [D10] -> string+ fromDigitList :: [Digit] -> string isDigitString :: string -> Bool isDigitString = isJust . toDigitListMaybe - toDigitListUnsafe :: string -> [D10]+ toDigitListUnsafe :: string -> [Digit] toDigitListUnsafe = fromJust . toDigitListMaybe - toDigitListMaybe :: string -> Maybe [D10]+ toDigitListMaybe :: string -> Maybe [Digit] toDigitListMaybe x = if isDigitString x then Just (toDigitListUnsafe x) else Nothing {-# minimal fromDigitList, ((isDigitString, toDigitListUnsafe) | toDigitListMaybe) #-}@@ -251,7 +288,7 @@ --- DigitSuperset instances --- -instance DigitSuperset D10+instance DigitSuperset Digit where isDigit _ = Bool.True fromDigit = id@@ -277,15 +314,15 @@ instance DigitSuperset char => DigitSuperset (ASCII char) where- isDigit = isDigit . lift+ isDigit = isDigit . ASCII.Refinement.lift fromDigit = asciiUnsafe . fromDigit- toDigitUnsafe = toDigitUnsafe . lift- toDigitMaybe = toDigitMaybe . lift+ toDigitUnsafe = toDigitUnsafe . ASCII.Refinement.lift+ toDigitMaybe = toDigitMaybe . ASCII.Refinement.lift --- DigitStringSuperset instances --- -instance DigitStringSuperset [D10]+instance DigitStringSuperset [Digit] where isDigitString _ = Bool.True fromDigitList = id@@ -340,7 +377,7 @@ instance DigitStringSuperset char => DigitStringSuperset (ASCII char) where- isDigitString = isDigitString . lift+ isDigitString = isDigitString . ASCII.Refinement.lift fromDigitList = asciiUnsafe . fromDigitList- toDigitListUnsafe = toDigitListUnsafe . lift- toDigitListMaybe = toDigitListMaybe . lift+ toDigitListUnsafe = toDigitListUnsafe . ASCII.Refinement.lift+ toDigitListMaybe = toDigitListMaybe . ASCII.Refinement.lift
library/ASCII/Hexadecimal.hs view
@@ -5,7 +5,7 @@ {- ** Integer -} showInteger, readInteger, {- ** Integral -} showIntegral, readIntegral, - {- * Various digit types -} D16 (..), HexChar (..), HexLetter (..), HexCharBreakdown (..),+ {- * Various digit types -} HexChar (..), HexLetter (..), HexCharBreakdown (..), {- * Monomorphic character conversions -} {- ** HexLetter ↔ D16 -} hexLetterD16, d16HexLetter,@@ -29,9 +29,12 @@ import ASCII.Case (Case (..)) import qualified ASCII.Char as ASCII import qualified ASCII.Decimal as Dec+import ASCII.Lift (Lift (lift)) import ASCII.Refinement (ASCII, asciiUnsafe, lift) import ASCII.Superset (StringSuperset, fromChar, fromCharList, toCharListMaybe, toCharMaybe)+import ASCII.Word4 (Word4)+import qualified ASCII.Word4 as Word4 import Control.Monad (guard, (<=<), (=<<)) import Data.Bifoldable (bifoldMap)@@ -71,27 +74,6 @@ --- Types --- --- | A whole number between /0/ and /15/-data D16- = D0 -- ^ Zero- | D1 -- ^ One- | D2 -- ^ Two- | D3 -- ^ Three- | D4 -- ^ Four- | D5 -- ^ Five- | D6 -- ^ Six- | D7 -- ^ Seven- | D8 -- ^ Eight- | D9 -- ^ Nine- | D10 -- ^ Ten (A)- | D11 -- ^ Eleven (B)- | D12 -- ^ Twelve (C)- | D13 -- ^ Thirteen (D)- | D14 -- ^ Fourteen (E)- | D15 -- ^ Fifteen (F)- deriving stock (Bounded, Enum, Eq, Ord, Show, Data, Generic)- deriving anyclass Hashable- -- | Letters used as hexadecimal digits above 9, without a notion of case. data HexLetter = LetterA -- ^ 10@@ -119,7 +101,7 @@ deriving stock (Bounded, Enum, Eq, Ord, Show, Data, Generic) deriving anyclass Hashable -data HexCharBreakdown = HexDigit Dec.D10 | HexLetter Case HexLetter+data HexCharBreakdown = HexDigit Dec.Digit | HexLetter Case HexLetter deriving stock (Eq, Ord, Show, Data, Generic) deriving anyclass Hashable @@ -152,17 +134,17 @@ HexLetter UpperCase x -> toEnum (fromEnum x + 10) HexLetter LowerCase x -> toEnum (fromEnum x + 16) -d16HexChar :: Case -> D16 -> HexChar+d16HexChar :: Case -> Word4 -> HexChar d16HexChar c = toEnum . case c of UpperCase -> fromEnum LowerCase -> \case- x | x <= D9 -> fromEnum x- x -> fromEnum x + 6+ x | x <= Word4.Number9 -> fromEnum x+ x -> fromEnum x + 6 -hexCharD16 :: HexChar -> D16+hexCharD16 :: HexChar -> Word4 hexCharD16 = \case x | x < SmallLetterA -> toEnum (fromEnum x)@@ -194,13 +176,13 @@ _ -> Nothing -hexLetterD16 :: HexLetter -> D16+hexLetterD16 :: HexLetter -> Word4 hexLetterD16 = toEnum . (\x -> x + 10) . fromEnum -d16HexLetter :: D16 -> Maybe HexLetter+d16HexLetter :: Word4 -> Maybe HexLetter d16HexLetter x = do- guard (x >= D10)+ guard (x >= Word4.Number10) Just (toEnum (fromEnum x - 10)) letterHexChar :: Case -> HexLetter -> HexChar@@ -277,32 +259,44 @@ . fromEnum -naturalD16Maybe :: Natural -> Maybe D16+naturalD16Maybe :: Natural -> Maybe Word4 naturalD16Maybe = \case x | x <= 15 -> Just (toEnum (fromIntegral x)) _ -> Nothing -d16Natural :: D16 -> Natural+d16Natural :: Word4 -> Natural d16Natural = fromIntegral . fromEnum -integerD16Maybe :: Integer -> Maybe D16+integerD16Maybe :: Integer -> Maybe Word4 integerD16Maybe = \case x | x < 0 -> Nothing x | x <= 15 -> Just (toEnum (fromInteger x)) _ -> Nothing -d16Integer :: D16 -> Integer+d16Integer :: Word4 -> Integer d16Integer = toInteger . fromEnum -naturalD16Unsafe :: Natural -> D16+naturalD16Unsafe :: Natural -> Word4 naturalD16Unsafe = toEnum . fromIntegral -integerD16Unsafe :: Integer -> D16+integerD16Unsafe :: Integer -> Word4 integerD16Unsafe = toEnum . fromIntegral +--- Lift instances ---++instance HexCharSuperset char => Lift HexChar char+ where+ lift = fromHexChar++instance HexStringSuperset string => Lift [HexChar] string+ where+ lift = fromHexCharList+++ --- Classes --- class HexCharSuperset char@@ -355,7 +349,7 @@ 0 -> fromHexCharList [ Digit0 ] n -> fromHexCharList (fmap (d16HexChar c) (naturalList n)) where- naturalList :: Natural -> [D16]+ naturalList :: Natural -> [Word4] naturalList = DList.toList . r where r = \case@@ -419,7 +413,7 @@ readNatural :: HexStringSuperset string => string -> Maybe Natural readNatural = (Just . readNaturalDigits) <=< nonEmpty <=< (Just . fmap hexCharD16) <=< toHexCharListMaybe where- readNaturalDigits :: NonEmpty D16 -> Natural+ readNaturalDigits :: NonEmpty Word4 -> Natural readNaturalDigits = List.foldl' (\total x -> (16 * total) + d16Natural x) 0 {- |@@ -447,7 +441,7 @@ readNonNegative :: [ASCII.Char] -> Maybe Integer readNonNegative = (Just . toInteger . readIntegerDigits) <=< nonEmpty <=< (Just . fmap hexCharD16) <=< toHexCharListMaybe - readIntegerDigits :: NonEmpty D16 -> Integer+ readIntegerDigits :: NonEmpty Word4 -> Integer readIntegerDigits = List.foldl' (\total x -> (16 * total) + d16Integer x) 0 {- |@@ -490,10 +484,10 @@ instance HexCharSuperset char => HexCharSuperset (ASCII char) where- isHexChar = isHexChar . lift+ isHexChar = isHexChar . ASCII.Refinement.lift fromHexChar = asciiUnsafe . fromHexChar- toHexCharUnsafe = toHexCharUnsafe . lift- toHexCharMaybe = toHexCharMaybe . lift+ toHexCharUnsafe = toHexCharUnsafe . ASCII.Refinement.lift+ toHexCharMaybe = toHexCharMaybe . ASCII.Refinement.lift --- HexStringSuperset instances ---@@ -553,7 +547,7 @@ instance HexStringSuperset char => HexStringSuperset (ASCII char) where- isHexString = isHexString . lift+ isHexString = isHexString . ASCII.Refinement.lift fromHexCharList = asciiUnsafe . fromHexCharList- toHexCharListUnsafe = toHexCharListUnsafe . lift- toHexCharListMaybe = toHexCharListMaybe . lift+ toHexCharListUnsafe = toHexCharListUnsafe . ASCII.Refinement.lift+ toHexCharListMaybe = toHexCharListMaybe . ASCII.Refinement.lift
+ library/ASCII/Word4.hs view
@@ -0,0 +1,30 @@+module ASCII.Word4 ( Word4 (..) ) where++import Data.Data (Data)+import Data.Eq (Eq)+import Data.Hashable (Hashable)+import Data.Ord (Ord (..))+import GHC.Generics (Generic)+import Prelude (Bounded (..), Enum (..))+import Text.Show (Show)++-- | 4-bit unsigned integer (a whole number between /0/ and /15/)+data Word4+ = Number0 -- ^ Zero+ | Number1 -- ^ One+ | Number2 -- ^ Two+ | Number3 -- ^ Three+ | Number4 -- ^ Four+ | Number5 -- ^ Five+ | Number6 -- ^ Six+ | Number7 -- ^ Seven+ | Number8 -- ^ Eight+ | Number9 -- ^ Nine+ | Number10 -- ^ Ten (A)+ | Number11 -- ^ Eleven (B)+ | Number12 -- ^ Twelve (C)+ | Number13 -- ^ Thirteen (D)+ | Number14 -- ^ Fourteen (E)+ | Number15 -- ^ Fifteen (F)+ deriving stock (Bounded, Enum, Eq, Ord, Show, Data, Generic)+ deriving anyclass Hashable
test/Main.hs view
@@ -4,6 +4,7 @@ import qualified ASCII.Char as ASCII import qualified ASCII.Decimal as Dec import qualified ASCII.Hexadecimal as Hex+import qualified ASCII.Word4 as Word4 import Control.Applicative (liftA2) import Control.Monad (Monad (..), when)@@ -123,7 +124,7 @@ prop_toDigitListMaybe :: Property prop_toDigitListMaybe = withTests 1 $ property $- Dec.toDigitListMaybe ("846" :: T.Text) === Just [Dec.D8, Dec.D4, Dec.D6]+ Dec.toDigitListMaybe ("846" :: T.Text) === Just [Dec.Digit8, Dec.Digit4, Dec.Digit6] prop_toDigitListMaybe_fail :: Property prop_toDigitListMaybe_fail = withTests 1 $ property $@@ -227,7 +228,7 @@ prop_naturalDigitMaybe_5 :: Property prop_naturalDigitMaybe_5 = withTests 1 $ property $- Dec.naturalDigitMaybe 5 === Just Dec.D5+ Dec.naturalDigitMaybe 5 === Just Dec.Digit5 prop_naturalDigitMaybe_12 :: Property prop_naturalDigitMaybe_12 = withTests 1 $ property $@@ -235,7 +236,7 @@ prop_integerDigitMaybe_5 :: Property prop_integerDigitMaybe_5 = withTests 1 $ property $- Dec.integerDigitMaybe 5 === Just Dec.D5+ Dec.integerDigitMaybe 5 === Just Dec.Digit5 prop_integerDigitMaybe_12 :: Property prop_integerDigitMaybe_12 = withTests 1 $ property $@@ -251,10 +252,10 @@ prop_D16_enumBounded :: Property prop_D16_enumBounded = withTests 1 $ property $ checkEnumBounded- [ Hex.D0, Hex.D1, Hex.D2, Hex.D3- , Hex.D4, Hex.D5, Hex.D6, Hex.D7- , Hex.D8, Hex.D9, Hex.D10, Hex.D11- , Hex.D12, Hex.D13, Hex.D14, Hex.D15+ [ Word4.Number0, Word4.Number1, Word4.Number2, Word4.Number3+ , Word4.Number4, Word4.Number5, Word4.Number6, Word4.Number7+ , Word4.Number8, Word4.Number9, Word4.Number10, Word4.Number11+ , Word4.Number12, Word4.Number13, Word4.Number14, Word4.Number15 ] prop_HexLetter_enumBounded :: Property@@ -278,16 +279,16 @@ prop_HexCharBreakdown_enumBounded :: Property prop_HexCharBreakdown_enumBounded = withTests 1 $ property $ checkEnumBounded- [ Hex.HexDigit Dec.D0- , Hex.HexDigit Dec.D1- , Hex.HexDigit Dec.D2- , Hex.HexDigit Dec.D3- , Hex.HexDigit Dec.D4- , Hex.HexDigit Dec.D5- , Hex.HexDigit Dec.D6- , Hex.HexDigit Dec.D7- , Hex.HexDigit Dec.D8- , Hex.HexDigit Dec.D9+ [ Hex.HexDigit Dec.Digit0+ , Hex.HexDigit Dec.Digit1+ , Hex.HexDigit Dec.Digit2+ , Hex.HexDigit Dec.Digit3+ , Hex.HexDigit Dec.Digit4+ , Hex.HexDigit Dec.Digit5+ , Hex.HexDigit Dec.Digit6+ , Hex.HexDigit Dec.Digit7+ , Hex.HexDigit Dec.Digit8+ , Hex.HexDigit Dec.Digit9 , Hex.HexLetter UpperCase Hex.LetterA , Hex.HexLetter UpperCase Hex.LetterB , Hex.HexLetter UpperCase Hex.LetterC@@ -313,12 +314,12 @@ prop_hexLetterD16 :: Property prop_hexLetterD16 = withTests 1 $ property $ functionEq every Hex.hexLetterD16 $ \case- Hex.LetterA -> Hex.D10- Hex.LetterB -> Hex.D11- Hex.LetterC -> Hex.D12- Hex.LetterD -> Hex.D13- Hex.LetterE -> Hex.D14- Hex.LetterF -> Hex.D15+ Hex.LetterA -> Word4.Number10+ Hex.LetterB -> Word4.Number11+ Hex.LetterC -> Word4.Number12+ Hex.LetterD -> Word4.Number13+ Hex.LetterE -> Word4.Number14+ Hex.LetterF -> Word4.Number15 prop_d16HexLetter :: Property prop_d16HexLetter = withTests 1 $ property $@@ -392,68 +393,68 @@ prop_d16HexChar :: Property prop_d16HexChar = withTests 1 $ property $ functionEq (liftA2 (,) every every) (uncurry Hex.d16HexChar) $ \case- (_, Hex.D0) -> Hex.Digit0- (_, Hex.D1) -> Hex.Digit1- (_, Hex.D2) -> Hex.Digit2- (_, Hex.D3) -> Hex.Digit3- (_, Hex.D4) -> Hex.Digit4- (_, Hex.D5) -> Hex.Digit5- (_, Hex.D6) -> Hex.Digit6- (_, Hex.D7) -> Hex.Digit7- (_, Hex.D8) -> Hex.Digit8- (_, Hex.D9) -> Hex.Digit9- (UpperCase, Hex.D10) -> Hex.CapitalLetterA- (UpperCase, Hex.D11) -> Hex.CapitalLetterB- (UpperCase, Hex.D12) -> Hex.CapitalLetterC- (UpperCase, Hex.D13) -> Hex.CapitalLetterD- (UpperCase, Hex.D14) -> Hex.CapitalLetterE- (UpperCase, Hex.D15) -> Hex.CapitalLetterF- (LowerCase, Hex.D10) -> Hex.SmallLetterA- (LowerCase, Hex.D11) -> Hex.SmallLetterB- (LowerCase, Hex.D12) -> Hex.SmallLetterC- (LowerCase, Hex.D13) -> Hex.SmallLetterD- (LowerCase, Hex.D14) -> Hex.SmallLetterE- (LowerCase, Hex.D15) -> Hex.SmallLetterF+ (_, Word4.Number0) -> Hex.Digit0+ (_, Word4.Number1) -> Hex.Digit1+ (_, Word4.Number2) -> Hex.Digit2+ (_, Word4.Number3) -> Hex.Digit3+ (_, Word4.Number4) -> Hex.Digit4+ (_, Word4.Number5) -> Hex.Digit5+ (_, Word4.Number6) -> Hex.Digit6+ (_, Word4.Number7) -> Hex.Digit7+ (_, Word4.Number8) -> Hex.Digit8+ (_, Word4.Number9) -> Hex.Digit9+ (UpperCase, Word4.Number10) -> Hex.CapitalLetterA+ (UpperCase, Word4.Number11) -> Hex.CapitalLetterB+ (UpperCase, Word4.Number12) -> Hex.CapitalLetterC+ (UpperCase, Word4.Number13) -> Hex.CapitalLetterD+ (UpperCase, Word4.Number14) -> Hex.CapitalLetterE+ (UpperCase, Word4.Number15) -> Hex.CapitalLetterF+ (LowerCase, Word4.Number10) -> Hex.SmallLetterA+ (LowerCase, Word4.Number11) -> Hex.SmallLetterB+ (LowerCase, Word4.Number12) -> Hex.SmallLetterC+ (LowerCase, Word4.Number13) -> Hex.SmallLetterD+ (LowerCase, Word4.Number14) -> Hex.SmallLetterE+ (LowerCase, Word4.Number15) -> Hex.SmallLetterF prop_hexCharD16 :: Property prop_hexCharD16 = withTests 1 $ property $ functionEq every Hex.hexCharD16 $ \case- Hex.Digit0 -> Hex.D0- Hex.Digit1 -> Hex.D1- Hex.Digit2 -> Hex.D2- Hex.Digit3 -> Hex.D3- Hex.Digit4 -> Hex.D4- Hex.Digit5 -> Hex.D5- Hex.Digit6 -> Hex.D6- Hex.Digit7 -> Hex.D7- Hex.Digit8 -> Hex.D8- Hex.Digit9 -> Hex.D9- Hex.CapitalLetterA -> Hex.D10- Hex.CapitalLetterB -> Hex.D11- Hex.CapitalLetterC -> Hex.D12- Hex.CapitalLetterD -> Hex.D13- Hex.CapitalLetterE -> Hex.D14- Hex.CapitalLetterF -> Hex.D15- Hex.SmallLetterA -> Hex.D10- Hex.SmallLetterB -> Hex.D11- Hex.SmallLetterC -> Hex.D12- Hex.SmallLetterD -> Hex.D13- Hex.SmallLetterE -> Hex.D14- Hex.SmallLetterF -> Hex.D15+ Hex.Digit0 -> Word4.Number0+ Hex.Digit1 -> Word4.Number1+ Hex.Digit2 -> Word4.Number2+ Hex.Digit3 -> Word4.Number3+ Hex.Digit4 -> Word4.Number4+ Hex.Digit5 -> Word4.Number5+ Hex.Digit6 -> Word4.Number6+ Hex.Digit7 -> Word4.Number7+ Hex.Digit8 -> Word4.Number8+ Hex.Digit9 -> Word4.Number9+ Hex.CapitalLetterA -> Word4.Number10+ Hex.CapitalLetterB -> Word4.Number11+ Hex.CapitalLetterC -> Word4.Number12+ Hex.CapitalLetterD -> Word4.Number13+ Hex.CapitalLetterE -> Word4.Number14+ Hex.CapitalLetterF -> Word4.Number15+ Hex.SmallLetterA -> Word4.Number10+ Hex.SmallLetterB -> Word4.Number11+ Hex.SmallLetterC -> Word4.Number12+ Hex.SmallLetterD -> Word4.Number13+ Hex.SmallLetterE -> Word4.Number14+ Hex.SmallLetterF -> Word4.Number15 prop_breakDownHexChar :: Property prop_breakDownHexChar = withTests 1 $ property $ functionEq every Hex.breakDownHexChar $ \case- Hex.Digit0 -> Hex.HexDigit Dec.D0- Hex.Digit1 -> Hex.HexDigit Dec.D1- Hex.Digit2 -> Hex.HexDigit Dec.D2- Hex.Digit3 -> Hex.HexDigit Dec.D3- Hex.Digit4 -> Hex.HexDigit Dec.D4- Hex.Digit5 -> Hex.HexDigit Dec.D5- Hex.Digit6 -> Hex.HexDigit Dec.D6- Hex.Digit7 -> Hex.HexDigit Dec.D7- Hex.Digit8 -> Hex.HexDigit Dec.D8- Hex.Digit9 -> Hex.HexDigit Dec.D9+ Hex.Digit0 -> Hex.HexDigit Dec.Digit0+ Hex.Digit1 -> Hex.HexDigit Dec.Digit1+ Hex.Digit2 -> Hex.HexDigit Dec.Digit2+ Hex.Digit3 -> Hex.HexDigit Dec.Digit3+ Hex.Digit4 -> Hex.HexDigit Dec.Digit4+ Hex.Digit5 -> Hex.HexDigit Dec.Digit5+ Hex.Digit6 -> Hex.HexDigit Dec.Digit6+ Hex.Digit7 -> Hex.HexDigit Dec.Digit7+ Hex.Digit8 -> Hex.HexDigit Dec.Digit8+ Hex.Digit9 -> Hex.HexDigit Dec.Digit9 Hex.CapitalLetterA -> Hex.HexLetter UpperCase Hex.LetterA Hex.CapitalLetterB -> Hex.HexLetter UpperCase Hex.LetterB Hex.CapitalLetterC -> Hex.HexLetter UpperCase Hex.LetterC