{-# LANGUAGE CPP #-} {-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE NoImplicitPrelude #-} -- | -- Module: $HEADER$ -- Description: Polymorphic interface for getting number of digits of a number -- in decimal or hexadecimal representation. -- Copyright: (c) 2015-2016, Peter Trško -- License: BSD3 -- -- Stability: experimental -- Portability: DefaultSignatures, NoImplicitPrelude -- -- Polymorphic interface for getting number of digits of a number in decimal or -- hexadecimal representation. module Data.NumberLength ( NumberLength(..) , SignedNumberLength(..) , BoundedNumberLength(..) ) where import Prelude(Integer, Num((+)), fromIntegral) import Data.Int (Int, Int16, Int32, Int64, Int8) import Data.Ord (Ord((<))) import Data.Word (Word, Word16, Word32, Word64, Word8) #ifdef HAVE_NATURAL import Numeric.Natural (Natural) #endif import Data.NumberLength.Int ( lengthInt , lengthInt16 , lengthInt16hex , lengthInt32 , lengthInt32hex , lengthInt64 , lengthInt64hex , lengthInt8 , lengthInt8hex , lengthIntHex ) import Data.NumberLength.Integer (lengthInteger, lengthIntegerHex) import Data.NumberLength.Internal (either32or64) #ifdef HAVE_NATURAL import Data.NumberLength.Natural (lengthNatural, lengthNaturalHex) #endif import Data.NumberLength.Word ( lengthWord , lengthWord16 , lengthWord16hex , lengthWord32 , lengthWord32hex , lengthWord64 , lengthWord64hex , lengthWord8 , lengthWord8hex , lengthWordHex ) -- | Get number of digits of a number in base 10 and base 16. Note the -- following: -- -- * There is no 'Num' constraint, so that type wrappers aren't forced to -- provide instance for it. This is because there are things represented -- using numbers, but they aren't numbers, e.g. telephone numbers. -- -- * This type class doesn't handle signed numbers, in an intuitive way. See -- also 'SignedNumberLength'. -- -- * There is a special class for bounded numbers, see 'BoundedNumberLength', -- that provides similar functionality as 'Prelude.Bounded', but for number -- of digits in a number. class NumberLength a where -- | Get number of digits in base 10 for specified number. Note that if -- number is signed, then this function will return length of its absolute -- value. -- -- >>> numberLength (123 :: Int) -- 3 -- >>> numberLength (-123 :: Int) -- 3 -- -- See also 'signedNumberLength'. numberLength :: a -> Int -- | Get number of digits in base 16 for specified number. Note that if -- number is signed, then this function will return length of its absolute -- value. -- -- >>> numberLengthHex (123 :: Int) -- 123 = 7b in hex -- 2 -- >>> numberLengthHex (-123 :: Int) -- 2 -- -- See also 'signedNumberLengthHex'. numberLengthHex :: a -> Int -- | Get number of digits of a signed number in base 10 and base 16. class NumberLength a => SignedNumberLength a where {-# MINIMAL signedNumberLengthHex #-} -- | Get number of digits in base 10 for specified number. -- -- >>> signedNumberLength (123 :: Int) -- 3 -- >>> signedNumberLength (-123 :: Int) -- 4 -- -- Default implementation provided if @a@ has also 'Num' and 'Ord' -- instances: -- -- @ -- 'signedNumberLength' n = signLength + 'numberLength' n -- where -- signLength = if n < 0 then 1 else 0 -- @ signedNumberLength :: a -> Int default signedNumberLength :: (Num a, Ord a) => a -> Int signedNumberLength n = signLength + numberLength n where signLength = if n < 0 then 1 else 0 -- | Get number of digits in base 16 for specified number. -- -- >>> signedNumberLengthHex (123 :: Int) -- 2 -- >>> signedNumberLengthHex (-123 :: Int) -- 16 -- -- Negative number is shown as ones' complement, e.g. @(-123 :: Int) = -- ffffffffffffff85@ on 64 bit platform. signedNumberLengthHex :: a -> Int -- | Get maximum number of digits of a number in base 10 and 16. Minimal number -- of digits is considered to be always 1, and therefore there is no method for -- it. class NumberLength a => BoundedNumberLength a where -- | Get maximum number of digits of a number in base 10. maxNumberLength :: proxy a -> Int -- | Get maximum number of digits of a number in base 16. maxNumberLengthHex :: proxy a -> Int -- {{{ Int* ------------------------------------------------------------------- instance NumberLength Int where numberLength = lengthInt numberLengthHex = lengthIntHex instance SignedNumberLength Int where signedNumberLengthHex n = numberLengthHex (fromIntegral n :: Word) instance BoundedNumberLength Int where maxNumberLength _ = 10 `either32or64` 19 maxNumberLengthHex _ = 8 `either32or64` 16 instance NumberLength Int64 where numberLength = lengthInt64 numberLengthHex = lengthInt64hex instance SignedNumberLength Int64 where signedNumberLengthHex n = numberLengthHex (fromIntegral n :: Word64) instance BoundedNumberLength Int64 where maxNumberLength _ = 19 maxNumberLengthHex _ = 16 instance NumberLength Int32 where numberLength = lengthInt32 numberLengthHex = lengthInt32hex instance SignedNumberLength Int32 where signedNumberLengthHex n = numberLengthHex (fromIntegral n :: Word32) instance BoundedNumberLength Int32 where maxNumberLength _ = 10 maxNumberLengthHex _ = 8 instance NumberLength Int16 where numberLength = lengthInt16 numberLengthHex = lengthInt16hex instance SignedNumberLength Int16 where signedNumberLengthHex n = numberLengthHex (fromIntegral n :: Word16) instance BoundedNumberLength Int16 where maxNumberLength _ = 5 maxNumberLengthHex _ = 4 instance NumberLength Int8 where numberLength = lengthInt8 numberLengthHex = lengthInt8hex instance SignedNumberLength Int8 where signedNumberLengthHex n = numberLengthHex (fromIntegral n :: Word8) instance BoundedNumberLength Int8 where maxNumberLength _ = 3 maxNumberLengthHex _ = 2 -- }}} Int* ------------------------------------------------------------------- -- {{{ Word* ------------------------------------------------------------------ instance NumberLength Word where numberLength = lengthWord numberLengthHex = lengthWordHex instance BoundedNumberLength Word where maxNumberLength _ = 10 `either32or64` 20 maxNumberLengthHex _ = 8 `either32or64` 16 instance NumberLength Word64 where numberLength = lengthWord64 numberLengthHex = lengthWord64hex instance BoundedNumberLength Word64 where maxNumberLength _ = 20 maxNumberLengthHex _ = 16 instance NumberLength Word32 where numberLength = lengthWord32 numberLengthHex = lengthWord32hex instance BoundedNumberLength Word32 where maxNumberLength _ = 10 maxNumberLengthHex _ = 8 instance NumberLength Word16 where numberLength = lengthWord16 numberLengthHex = lengthWord16hex instance BoundedNumberLength Word16 where maxNumberLength _ = 5 maxNumberLengthHex _ = 4 instance NumberLength Word8 where numberLength = lengthWord8 numberLengthHex = lengthWord8hex instance BoundedNumberLength Word8 where maxNumberLength _ = 3 maxNumberLengthHex _ = 2 -- }}} Word* ------------------------------------------------------------------ -- | /Since 0.2.0.0/ instance NumberLength Integer where numberLength = lengthInteger numberLengthHex = lengthIntegerHex #ifdef HAVE_NATURAL -- | /Since 0.2.0.0/ instance NumberLength Natural where numberLength = lengthNatural numberLengthHex = lengthNaturalHex #endif