Documentation
Repr a
is a value of type a
paired with a way to render that value to a
string which will contain a representation of the value.
Note that Repr a
is overloaded for all the numeric classes provided that
a
has instances for the respected classes. This allows you to write a
numeric expression of type Repr a
. For example:
*Repr> let rd = 1.5 + 2 + (3 + (-4) * (5 - pi / sqrt 6)) :: Repr Double
You can extract the value of rd
:
*Repr> value rd 17.281195923884734
And you can than render rd
to its textual representation:
*Repr> render rd "fromRational (3 % 2) + fromInteger 2 + (fromInteger 3 + negate (fromInteger 4) * (fromInteger 5 - pi / sqrt (fromInteger 6)))"
Enum a => Enum (Repr a) | |
Eq a => Eq (Repr a) | |
Floating a => Floating (Repr a) | |
Fractional a => Fractional (Repr a) | |
Integral a => Integral (Repr a) | |
Num a => Num (Repr a) | |
Ord a => Ord (Repr a) | |
Real a => Real (Repr a) | |
RealFloat a => RealFloat (Repr a) | |
RealFrac a => RealFrac (Repr a) | |
Show (Repr a) | |
IsString a => IsString (Repr a) |
type Renderer = Precedence -> Fixity -> DStringSource
To render you need to supply the precedence and fixity of the enclosing context.
For more documentation about precedence and fixity see:
http://haskell.org/onlinereport/decls.html#sect4.4.2
The reason the renderer returns a DString
instead of for example a String
is that the rendering of numeric expression involves lots of left-factored
appends i.e.: ((a ++ b) ++ c) ++ d
. A DString
has a O(1) append operation
while a String
just has a O(n) append. So choosing a DString
is more
efficient.
type Precedence = IntSource
The precedence of operators and function application.
- Operators usually have a precedence in the range of 0 to 9.
- Function application always has precedence 10.
Fixity of operators.
(<?>) :: Repr a -> DString -> Repr aSource
x <?> s
annotates the rendering with the given string.
The output wil look like: "({- s -} ...)"
where ...
is the rendering of
x
.
This combinator is handy when you want to render the ouput of a function and
you want to see how the parameters of the function contribute to the
result. For example, suppose you defined the following function f
:
f p0 p1 p2 = p0 ^ 2 + sqrt p1 * ([p2..] !! 10)
You can then apply f
to some parameters annotated with some descriptive
strings (the name of the parameter is usally a good idea):
f (1 <?> "p0") (2 <?> "p1") (3 <?> "p2")
The rendering will then look like:
"({- p0 -} fromInteger 1) * ({- p0 -} fromInteger 1) + sqrt ({- p1 -} (fromInteger 2)) * enumFrom ({- p2 -} (fromInteger 3)) !! 10"