I'm looking for a numeric type able to represent, say, a value 0.213123
or 0.0
, or 1.0
, but refusing the out of range values, such as -0.2123
and 1.2312
. Does there exist a specific type fitting that purpose, and what is the optimal general approach to restricting numbers to a specific range?
Of course, the first answer coming to mind is: just use Double
, but getting spoiled by Haskell's type system I've gotten used to maximally securing the program on a type level.
So how many “normal” non-zero numbers are there between 0 and 1? The negative exponents range from -1 all the way to -126. In each case, we have 223 distinct floating-point numbers because the mantissa is made of 23 bits. So we have 126 x 223 normal floating-point numbers in [0,1).
A single-precision, floating-point number is a 32-bit approximation of a real number. The number can be zero or can range from -3.40282347E+38 to -1.17549435E-38, or from 1.17549435E-38 to 3.40282347E+38.
A Floating Point number usually has a decimal point. This means that 0, 3.14, 6.5, and -125.5 are Floating Point numbers.
A Serious Suggestions
You could use a newtype wrapper (and smart constructor) around a word of the proper bit size:
newtype SmallFrac = SF Word64
-- Example conversion (You'd actually want to make
-- instances of common classes, I assume)
sfToDouble :: SmallFrac -> Double
sfToDouble (SF x) = fromIntegral x / fromIntegral (maxBound `asTypeOf` x)
instance Show SmallFrac where
show = show . sfToDouble
Implementing multiplication and division might be more costly than you would like, but at least addition is easy (modulo protecting against over/underflow) and you claim to not need any operations so even better.
A Less Useful Suggestion
If all you need is a symbol representing a value exists between one and zero then take dave4420's suggestion and just have a unit type:
newtype SmallFrac = SF ()
There are no operations for this type, not even conversion to/from other types of interest such as Double
, but this meets the request as stated.
Not standard. You'd have to make one -- I'd suggest a smart constructor. Keep in mind though that such a type supports very few numeric operations -- you can't add them and keep them in the set, nor negate them, so I would advise against a Num
instance. A Monoid
on multiplication would be reasonable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With