@@ -25,6 +25,7 @@ You can create additional representations by making instances of the
2525--
2626module Truncate
2727 ( Truncatable (.. )
28+ , TParser
2829 , WordF (.. )
2930 , Binary (.. )
3031 , Decimal (.. )
@@ -51,6 +52,7 @@ import Data.Binary.IEEE754 ( wordToFloat
5152import Numeric ( readInt
5253 , readHex
5354 )
55+ import Text.Read (readMaybe )
5456
5557
5658------------------------------------------------------------------------
@@ -82,6 +84,11 @@ class Truncatable a where
8284 convert = fromBits . makeBits
8385
8486
87+ -----------------------------------------------------------------------
88+ -- | A function type for parsing 'Truncatable' types
89+ type TParser a = String -> Either String a
90+
91+
8592-----------------------------------------------------------------------
8693-- | Truncatable floating-point numbers in binary representation.
8794data Binary = Bin32 String
@@ -108,17 +115,19 @@ toBin = convert
108115
109116-- | Create a 'Bin32' from a string. The string should be a sequence of the
110117-- characters @0@ and @1@ no longer than 32 characters in length.
111- makeBin32 :: String -> Binary
118+ makeBin32 :: TParser Binary
112119makeBin32 s
113- | length s <= 32 && validBin s = Bin32 s
114- | otherwise = error $ " invalid 32-bit binary: " ++ s
120+ | length s > 32 = Left $ tooManyDigits " binary" 32
121+ | (not . validBin) s = Left $ invalidDigits " binary" 32
122+ | otherwise = Right (Bin32 s)
115123
116124-- | Create a 'Bin64' from a string. The string should be a sequence of the
117125-- characters @0@ and @1@ no longer than 64 characters in length.
118- makeBin64 :: String -> Binary
126+ makeBin64 :: TParser Binary
119127makeBin64 s
120- | length s <= 64 && validBin s = Bin64 s
121- | otherwise = error $ " invalid 64-bit binary: " ++ s
128+ | length s > 64 = Left $ tooManyDigits " binary" 64
129+ | (not . validBin) s = Left $ invalidDigits " binary" 64
130+ | otherwise = Right (Bin64 s)
122131
123132
124133-----------------------------------------------------------------------
@@ -143,13 +152,17 @@ toDec = convert
143152
144153-- | Create a 'Dec32' from a string. The string can be anything that can be
145154-- interpreted as a 32-bit 'Float' by 'read'.
146- makeDec32 :: String -> Decimal
147- makeDec32 s = Dec32 (read s :: Float )
155+ makeDec32 :: TParser Decimal
156+ makeDec32 s = case readMaybe s :: Maybe Float of
157+ Just f -> Right (Dec32 f)
158+ Nothing -> Left " Error: value is not a 32-bit decimal number"
148159
149160-- | Create a 'Dec64' from a string. The string can be anything that can be
150161-- interpreted as a 64-bit 'Double' by 'read'.
151- makeDec64 :: String -> Decimal
152- makeDec64 s = Dec64 (read s :: Double )
162+ makeDec64 :: TParser Decimal
163+ makeDec64 s = case readMaybe s :: Maybe Double of
164+ Just f -> Right (Dec64 f)
165+ Nothing -> Left " Error: value is not a 64-bit decimal number"
153166
154167
155168-----------------------------------------------------------------------
@@ -178,14 +191,16 @@ toHex = convert
178191
179192-- | Create a 'Hex32' from a string. The string should be a sequence of the
180193-- valid hexadecimal digits @0-9@ and @a-f@ no longer than 8 characters in length.
181- makeHex32 :: String -> Hexadecimal
194+ makeHex32 :: TParser Hexadecimal
182195makeHex32 s
183- | length s <= 8 && validHex s = Hex32 s
184- | otherwise = error $ " invalid 32-bit hexadecimal: " ++ s
196+ | length s > 8 = Left $ tooManyDigits " hexadecimal" 32
197+ | (not . validHex) s = Left $ invalidDigits " hexadecimal" 32
198+ | otherwise = Right (Hex32 s)
185199
186200-- | Create a 'Hex64' from a string. The string should be a sequence of the
187201-- valid hexadecimal digits @0-9@ and @a-f@ no longer than 16 characters in length.
188- makeHex64 :: String -> Hexadecimal
202+ makeHex64 :: TParser Hexadecimal
189203makeHex64 s
190- | length s <= 16 && validHex s = Hex64 s
191- | otherwise = error $ " invalid 64-bit hexadecimal: " ++ s
204+ | length s > 16 = Left $ tooManyDigits " hexadecimal" 64
205+ | (not . validHex) s = Left $ invalidDigits " hexadecimal" 64
206+ | otherwise = Right (Hex64 s)
0 commit comments