Copyright | Copyright (c) 2015--2021 wren gayle romano |
---|---|

License | BSD2 |

Maintainer | wren@cpan.org |

Stability | provisional |

Portability | BangPatterns + ScopedTypeVariables |

Safe Haskell | None |

Language | Haskell2010 |

Functions for parsing and producing `Fractional`

values from/to
`ByteString`

s based on the "Char8" encoding. That is, we assume
an ASCII-compatible encoding of alphanumeric characters.

*Since: 0.5.0*

## Synopsis

- readSigned :: Num a => (ByteString -> Maybe (a, ByteString)) -> ByteString -> Maybe (a, ByteString)
- readDecimal :: Fractional a => ByteString -> Maybe (a, ByteString)
- readHexadecimal :: Fractional a => ByteString -> Maybe (a, ByteString)
- readOctal :: Fractional a => ByteString -> Maybe (a, ByteString)
- readExponential :: Fractional a => ByteString -> Maybe (a, ByteString)
- decimalPrecision :: forall proxy a. RealFloat a => proxy a -> Int
- readDecimalLimited :: Fractional a => Int -> ByteString -> Maybe (a, ByteString)
- readExponentialLimited :: Fractional a => Int -> ByteString -> Maybe (a, ByteString)

# General combinators

readSigned :: Num a => (ByteString -> Maybe (a, ByteString)) -> ByteString -> Maybe (a, ByteString) Source #

Adjust a reading function to recognize an optional leading sign. As with the other functions, we assume an ASCII-compatible encoding of the sign characters.

# Decimal conversions

readDecimal :: Fractional a => ByteString -> Maybe (a, ByteString) Source #

Read an unsigned/non-negative fractional value in ASCII decimal
format; that is, anything matching the regex `\d+(\.\d+)?`

.
Returns `Nothing`

if there is no such number at the beginning
of the string, otherwise returns `Just`

the number read and the
remainder of the string.

N.B., see `readDecimalLimited`

if your fractional type has limited
precision and you expect your inputs to have greater precision
than can be represented. Even for types with unlimited precision
(e.g., `Rational`

), you may want to check out `readDecimalLimited`

.

# Hexadecimal conversions

readHexadecimal :: Fractional a => ByteString -> Maybe (a, ByteString) Source #

Read a non-negative integral value in ASCII hexadecimal format.
Returns `Nothing`

if there is no integer at the beginning of the
string, otherwise returns `Just`

the integer read and the remainder
of the string.

This function does not recognize the various hexadecimal sigils like "0x", but because there are so many different variants, those are best handled by helper functions which then use this function for the actual numerical parsing. This function recognizes both upper-case, lower-case, and mixed-case hexadecimal.

This is just a thin wrapper around `readHexadecimal`

.

# Octal conversions

readOctal :: Fractional a => ByteString -> Maybe (a, ByteString) Source #

Read a non-negative integral value in ASCII octal format.
Returns `Nothing`

if there is no integer at the beginning of the
string, otherwise returns `Just`

the integer read and the remainder
of the string.

This function does not recognize the various octal sigils like "0o", but because there are different variants, those are best handled by helper functions which then use this function for the actual numerical parsing.

This is just a thin wrapper around `readOctal`

.

# Exponential conversions

readExponential :: Fractional a => ByteString -> Maybe (a, ByteString) Source #

Read an unsigned/non-negative fractional value in ASCII
exponential format; that is, anything matching the regex
`\d+(\.\d+)?([eE][\+\-]?\d+)?`

. Returns `Nothing`

if there
is no such number at the beginning of the string, otherwise
returns `Just`

the number read and the remainder of the string.

N.B., the current implementation assumes the exponent is small
enough to fit into an `Int`

. This gives a significant performance
increase for `a ~ Float`

and `a ~ Double`

and agrees with the
`RealFloat`

class which has `exponent`

returning an `Int`

. If
you need a larger exponent, contact the maintainer.

N.B., see `readExponentialLimited`

if your fractional type has
limited precision and you expect your inputs to have greater
precision than can be represented. Even for types with unlimited
precision, you may want to check out `readExponentialLimited`

.

# Precision-limited conversions

decimalPrecision :: forall proxy a. RealFloat a => proxy a -> Int Source #

Return the `RealFloat`

type's inherent decimal precision
limitation. This is the number of decimal digits in ```
floatRadix
proxy ^ floatDigits proxy
```

.

readDecimalLimited :: Fractional a => Int -> ByteString -> Maybe (a, ByteString) Source #

A variant of `readDecimal`

which only reads up to some limited
precision. The first argument gives the number of decimal digits
at which to limit the precision.

For types with inherently limited precision (e.g., `Float`

and
`Double`

), when you pass in the precision limit (cf.,
`decimalPrecision`

) this is far more efficient than `readDecimal`

.
However, passing in a precision limit which is greater than the
type's inherent limitation will degrate performance compared to
`readDecimal`

.

For types with unlimited precision (e.g., `Rational`

) this may
still be far more efficient than `readDecimal`

(it is for
`Rational`

, in fact). The reason being that it delays the scaling
the significand/mantissa by the exponent, thus allowing you to
further adjust the exponent before computing the final value
(e.g., as in `readExponentialLimited`

). This avoids the need to
renormalize intermediate results, and allows faster computation
of the scaling factor by doing it all at once.

readExponentialLimited :: Fractional a => Int -> ByteString -> Maybe (a, ByteString) Source #

A variant of `readExponential`

which only reads up to some limited
precision. The first argument gives the number of decimal digits
at which to limit the precision. See `readDecimalLimited`

for
more discussion of the performance benefits of using this function.