Copyright | (c) 2011-2015 diagrams-core team (see LICENSE) |
---|---|
License | BSD-style (see LICENSE) |
Maintainer | diagrams-discuss@googlegroups.com |
Safe Haskell | None |
Language | Haskell2010 |
The core library of primitives forming the basis of an embedded domain-specific language for describing and rendering diagrams.
Diagrams.Core.Types defines types and classes for primitives, diagrams, and backends.
- data Annotation
- applyAnnotation :: (Metric v, OrderedField n, Semigroup m) => Annotation -> QDiagram b v n m -> QDiagram b v n m
- href :: (Metric v, OrderedField n, Semigroup m) => String -> QDiagram b v n m -> QDiagram b v n m
- opacityGroup :: (Metric v, OrderedField n, Semigroup m) => Double -> QDiagram b v n m -> QDiagram b v n m
- groupOpacity :: (Metric v, OrderedField n, Semigroup m) => Double -> QDiagram b v n m -> QDiagram b v n m
- type UpAnnots b v n m = Deletable (Envelope v n) ::: (Deletable (Trace v n) ::: (Deletable (SubMap b v n m) ::: (Query v n m ::: ())))
- type DownAnnots v n = (Transformation v n :+: Style v n) ::: (Name ::: ())
- transfToAnnot :: Transformation v n -> DownAnnots v n
- transfFromAnnot :: (Additive v, Num n) => DownAnnots v n -> Transformation v n
- data QDiaLeaf b v n m
- = PrimLeaf (Prim b v n)
- | DelayedLeaf (DownAnnots v n -> n -> n -> QDiagram b v n m)
- withQDiaLeaf :: (Prim b v n -> r) -> ((DownAnnots v n -> n -> n -> QDiagram b v n m) -> r) -> QDiaLeaf b v n m -> r
- newtype QDiagram b v n m = QD (DUALTree (DownAnnots v n) (UpAnnots b v n m) Annotation (QDiaLeaf b v n m))
- type Diagram b = QDiagram b (V b) (N b) Any
- mkQD :: Prim b v n -> Envelope v n -> Trace v n -> SubMap b v n m -> Query v n m -> QDiagram b v n m
- mkQD' :: QDiaLeaf b v n m -> Envelope v n -> Trace v n -> SubMap b v n m -> Query v n m -> QDiagram b v n m
- pointDiagram :: (Metric v, Fractional n) => Point v n -> QDiagram b v n m
- envelope :: (OrderedField n, Metric v, Monoid' m) => Lens' (QDiagram b v n m) (Envelope v n)
- trace :: (Metric v, OrderedField n, Semigroup m) => Lens' (QDiagram b v n m) (Trace v n)
- subMap :: (Metric v, Semigroup m, OrderedField n) => Lens' (QDiagram b v n m) (SubMap b v n m)
- names :: (Metric v, Semigroup m, OrderedField n) => QDiagram b v n m -> [(Name, [Point v n])]
- query :: Monoid m => QDiagram b v n m -> Query v n m
- sample :: Monoid m => QDiagram b v n m -> Point v n -> m
- value :: Monoid m => m -> QDiagram b v n Any -> QDiagram b v n m
- resetValue :: (Eq m, Monoid m) => QDiagram b v n m -> QDiagram b v n Any
- clearValue :: QDiagram b v n m -> QDiagram b v n Any
- atop :: (OrderedField n, Metric v, Semigroup m) => QDiagram b v n m -> QDiagram b v n m -> QDiagram b v n m
- nameSub :: (IsName nm, Metric v, OrderedField n, Semigroup m) => (QDiagram b v n m -> Subdiagram b v n m) -> nm -> QDiagram b v n m -> QDiagram b v n m
- lookupName :: (IsName nm, Metric v, Semigroup m, OrderedField n) => nm -> QDiagram b v n m -> Maybe (Subdiagram b v n m)
- withName :: (IsName nm, Metric v, Semigroup m, OrderedField n) => nm -> (Subdiagram b v n m -> QDiagram b v n m -> QDiagram b v n m) -> QDiagram b v n m -> QDiagram b v n m
- withNameAll :: (IsName nm, Metric v, Semigroup m, OrderedField n) => nm -> ([Subdiagram b v n m] -> QDiagram b v n m -> QDiagram b v n m) -> QDiagram b v n m -> QDiagram b v n m
- withNames :: (IsName nm, Metric v, Semigroup m, OrderedField n) => [nm] -> ([Subdiagram b v n m] -> QDiagram b v n m -> QDiagram b v n m) -> QDiagram b v n m -> QDiagram b v n m
- localize :: forall b v n m. (Metric v, OrderedField n, Semigroup m) => QDiagram b v n m -> QDiagram b v n m
- setEnvelope :: forall b v n m. (OrderedField n, Metric v, Monoid' m) => Envelope v n -> QDiagram b v n m -> QDiagram b v n m
- setTrace :: forall b v n m. (OrderedField n, Metric v, Semigroup m) => Trace v n -> QDiagram b v n m -> QDiagram b v n m
- data Subdiagram b v n m = Subdiagram (QDiagram b v n m) (DownAnnots v n)
- mkSubdiagram :: QDiagram b v n m -> Subdiagram b v n m
- getSub :: (Metric v, OrderedField n, Semigroup m) => Subdiagram b v n m -> QDiagram b v n m
- rawSub :: Subdiagram b v n m -> QDiagram b v n m
- location :: (Additive v, Num n) => Subdiagram b v n m -> Point v n
- subPoint :: (Metric v, OrderedField n, Semigroup m) => Point v n -> Subdiagram b v n m
- newtype SubMap b v n m = SubMap (Map Name [Subdiagram b v n m])
- fromNames :: IsName a => [(a, Subdiagram b v n m)] -> SubMap b v n m
- rememberAs :: IsName a => a -> QDiagram b v n m -> SubMap b v n m -> SubMap b v n m
- lookupSub :: IsName nm => nm -> SubMap b v n m -> Maybe [Subdiagram b v n m]
- data Prim b v n where
- Prim :: (Transformable p, Typeable p, Renderable p b) => p -> Prim b (V p) (N p)
- _Prim :: (Transformable p, Typeable p, Renderable p b) => Prism' (Prim b (V p) (N p)) p
- class Backend b v n where
- type DTree b v n a = Tree (DNode b v n a)
- data DNode b v n a
- = DStyle (Style v n)
- | DTransform (Transformation v n)
- | DAnnot a
- | DDelay
- | DPrim (Prim b v n)
- | DEmpty
- type RTree b v n a = Tree (RNode b v n a)
- data RNode b v n a
- _RStyle :: Prism' (RNode b v n a) (Style v n)
- _RAnnot :: Prism' (RNode b v n a) a
- _RPrim :: Prism' (RNode b v n a) (Prim b v n)
- _REmpty :: Prism' (RNode b v n a) ()
- data NullBackend
- type D v n = QDiagram NullBackend v n Any
- class (Typeable n, RealFloat n) => TypeableFloat n
- class Transformable t => Renderable t b where
Diagrams
Annotations
Static annotations
data Annotation Source
Static annotations which can be placed at a particular node of a diagram tree.
Href String | Hyperlink |
OpacityGroup Double |
applyAnnotation :: (Metric v, OrderedField n, Semigroup m) => Annotation -> QDiagram b v n m -> QDiagram b v n m Source
Apply a static annotation at the root of a diagram.
href :: (Metric v, OrderedField n, Semigroup m) => String -> QDiagram b v n m -> QDiagram b v n m Source
Make a diagram into a hyperlink. Note that only some backends will honor hyperlink annotations.
opacityGroup :: (Metric v, OrderedField n, Semigroup m) => Double -> QDiagram b v n m -> QDiagram b v n m Source
Change the transparency of a Diagram
as a group.
groupOpacity :: (Metric v, OrderedField n, Semigroup m) => Double -> QDiagram b v n m -> QDiagram b v n m Source
Change the transparency of a Diagram
as a group.
Dynamic (monoidal) annotations
type UpAnnots b v n m = Deletable (Envelope v n) ::: (Deletable (Trace v n) ::: (Deletable (SubMap b v n m) ::: (Query v n m ::: ()))) Source
Monoidal annotations which travel up the diagram tree, i.e. which are aggregated from component diagrams to the whole:
- envelopes (see Diagrams.Core.Envelope). The envelopes are "deletable" meaning that at any point we can throw away the existing envelope and replace it with a new one; sometimes we want to consider a diagram as having a different envelope unrelated to its "natural" envelope.
- traces (see Diagrams.Core.Trace), also deletable.
- name/subdiagram associations (see Diagrams.Core.Names)
- query functions (see Diagrams.Core.Query)
type DownAnnots v n = (Transformation v n :+: Style v n) ::: (Name ::: ()) Source
Monoidal annotations which travel down the diagram tree, i.e. which accumulate along each path to a leaf (and which can act on the upwards-travelling annotations):
- styles (see Diagrams.Core.Style)
- names (see Diagrams.Core.Names)
transfToAnnot :: Transformation v n -> DownAnnots v n Source
Inject a transformation into a default downwards annotation value.
transfFromAnnot :: (Additive v, Num n) => DownAnnots v n -> Transformation v n Source
Extract the (total) transformation from a downwards annotation value.
Basic type definitions
A leaf in a QDiagram
tree is either a Prim
, or a "delayed"
QDiagram
which expands to a real QDiagram
once it learns the
"final context" in which it will be rendered. For example, in
order to decide how to draw an arrow, we must know the precise
transformation applied to it (since the arrow head and tail are
scale-invariant).
PrimLeaf (Prim b v n) | |
DelayedLeaf (DownAnnots v n -> n -> n -> QDiagram b v n m) | The |
withQDiaLeaf :: (Prim b v n -> r) -> ((DownAnnots v n -> n -> n -> QDiagram b v n m) -> r) -> QDiaLeaf b v n m -> r Source
newtype QDiagram b v n m Source
The fundamental diagram type. The type variables are as follows:
b
represents the backend, such asSVG
orCairo
. Note that each backend also exports a type synonymB
for itself, so the type variableb
may also typically be instantiated byB
, meaning "use whatever backend is in scope".v
represents the vector space of the diagram. Typical instantiations includeV2
(for a two-dimensional diagram) orV3
(for a three-dimensional diagram).n
represents the numerical field the diagram uses. Typically this will be a concrete numeric type likeDouble
.m
is the monoidal type of "query annotations": each point in the diagram has a value of typem
associated to it, and these values are combined according to theMonoid
instance form
. Most often,m
is simply instantiated toAny
, associating a simpleBool
value to each point indicating whether the point is inside the diagram;Diagram
is a synonym forQDiagram
withm
thus instantiated toAny
.
Diagrams can be combined via their Monoid
instance, transformed
via their Transformable
instance, and assigned attributes via
their HasStyle
instance.
Note that the Q
in QDiagram
stands for "Queriable", as
distinguished from Diagram
, where m
is fixed to Any
. This
is not really a very good name, but it's probably not worth
changing it at this point.
QD (DUALTree (DownAnnots v n) (UpAnnots b v n m) Annotation (QDiaLeaf b v n m)) |
Functor (QDiagram b v n) Source | |
(Metric v, OrderedField n, Semigroup m) => Monoid (QDiagram b v n m) Source | Diagrams form a monoid since each of their components do: the empty diagram has no primitives, an empty envelope, an empty trace, no named subdiagrams, and a constantly empty query function. Diagrams compose by aligning their respective local origins. The new diagram has all the primitives and all the names from the two diagrams combined, and query functions are combined pointwise. The first diagram goes on top of the second. "On top of" probably only makes sense in vector spaces of dimension lower than 3, but in theory it could make sense for, say, 3-dimensional diagrams when viewed by 4-dimensional beings. |
(Metric v, OrderedField n, Semigroup m) => Semigroup (QDiagram b v n m) Source | |
Wrapped (QDiagram b v n m) Source | |
(Metric v, OrderedField n, Semigroup m) => HasOrigin (QDiagram b v n m) Source | Every diagram has an intrinsic "local origin" which is the basis for all combining operations. |
(OrderedField n, Metric v, Semigroup m) => Transformable (QDiagram b v n m) Source | Diagrams can be transformed by transforming each of their components appropriately. |
(Metric v, OrderedField n, Semigroup m) => Qualifiable (QDiagram b v n m) Source | Diagrams can be qualified so that all their named points can now be referred to using the qualification prefix. |
(Metric v, OrderedField n, Semigroup m) => HasStyle (QDiagram b v n m) Source | |
(Metric v, OrderedField n, Semigroup m) => Traced (QDiagram b v n m) Source | |
(Metric v, OrderedField n, Monoid' m) => Enveloped (QDiagram b v n m) Source | |
(Metric v, OrderedField n, Monoid' m) => Juxtaposable (QDiagram b v n m) Source | |
Rewrapped (QDiagram b v n m) (QDiagram b' v' n' m') Source | |
type Unwrapped (QDiagram b v n m) = DUALTree (DownAnnots v n) (UpAnnots b v n m) Annotation (QDiaLeaf b v n m) Source | |
type N (QDiagram b v n m) = n Source | |
type V (QDiagram b v n m) = v Source |
type Diagram b = QDiagram b (V b) (N b) Any Source
Diagram b
is a synonym for
. That is,
the default sort of diagram is one where querying at a point
simply tells you whether the diagram contains that point or not.
Transforming a default diagram into one with a more interesting
query can be done via the QDiagram
b (V b) (N b) Any
Functor
instance of
or
the QDiagram
b v nvalue
function.
Operations on diagrams
Creating diagrams
mkQD :: Prim b v n -> Envelope v n -> Trace v n -> SubMap b v n m -> Query v n m -> QDiagram b v n m Source
Create a diagram from a single primitive, along with an envelope, trace, subdiagram map, and query function.
mkQD' :: QDiaLeaf b v n m -> Envelope v n -> Trace v n -> SubMap b v n m -> Query v n m -> QDiagram b v n m Source
Create a diagram from a generic QDiaLeaf, along with an envelope, trace, subdiagram map, and query function.
pointDiagram :: (Metric v, Fractional n) => Point v n -> QDiagram b v n m Source
Create a "point diagram", which has no content, no trace, an empty query, and a point envelope.
Extracting information
subMap :: (Metric v, Semigroup m, OrderedField n) => Lens' (QDiagram b v n m) (SubMap b v n m) Source
names :: (Metric v, Semigroup m, OrderedField n) => QDiagram b v n m -> [(Name, [Point v n])] Source
Get a list of names of subdiagrams and their locations.
query :: Monoid m => QDiagram b v n m -> Query v n m Source
Get the query function associated with a diagram.
sample :: Monoid m => QDiagram b v n m -> Point v n -> m Source
Sample a diagram's query function at a given point.
clearValue :: QDiagram b v n m -> QDiagram b v n Any Source
Set all the query values of a diagram to False
.
Combining diagrams
For many more ways of combining diagrams, see Diagrams.Combinators and Diagrams.TwoD.Combinators from the diagrams-lib package.
atop :: (OrderedField n, Metric v, Semigroup m) => QDiagram b v n m -> QDiagram b v n m -> QDiagram b v n m infixl 6 Source
A convenient synonym for mappend
on diagrams, designed to be
used infix (to help remember which diagram goes on top of which
when combining them, namely, the first on top of the second).
Modifying diagrams
Names
nameSub :: (IsName nm, Metric v, OrderedField n, Semigroup m) => (QDiagram b v n m -> Subdiagram b v n m) -> nm -> QDiagram b v n m -> QDiagram b v n m Source
Attach an atomic name to a certain subdiagram, computed from the
given diagram /with the mapping from name to subdiagram
included/. The upshot of this knot-tying is that if d' = d #
named x
, then lookupName x d' == Just d'
(instead of Just
d
).
lookupName :: (IsName nm, Metric v, Semigroup m, OrderedField n) => nm -> QDiagram b v n m -> Maybe (Subdiagram b v n m) Source
Lookup the most recent diagram associated with (some qualification of) the given name.
withName :: (IsName nm, Metric v, Semigroup m, OrderedField n) => nm -> (Subdiagram b v n m -> QDiagram b v n m -> QDiagram b v n m) -> QDiagram b v n m -> QDiagram b v n m Source
Given a name and a diagram transformation indexed by a subdiagram, perform the transformation using the most recent subdiagram associated with (some qualification of) the name, or perform the identity transformation if the name does not exist.
withNameAll :: (IsName nm, Metric v, Semigroup m, OrderedField n) => nm -> ([Subdiagram b v n m] -> QDiagram b v n m -> QDiagram b v n m) -> QDiagram b v n m -> QDiagram b v n m Source
Given a name and a diagram transformation indexed by a list of subdiagrams, perform the transformation using the collection of all such subdiagrams associated with (some qualification of) the given name.
withNames :: (IsName nm, Metric v, Semigroup m, OrderedField n) => [nm] -> ([Subdiagram b v n m] -> QDiagram b v n m -> QDiagram b v n m) -> QDiagram b v n m -> QDiagram b v n m Source
Given a list of names and a diagram transformation indexed by a list of subdiagrams, perform the transformation using the list of most recent subdiagrams associated with (some qualification of) each name. Do nothing (the identity transformation) if any of the names do not exist.
localize :: forall b v n m. (Metric v, OrderedField n, Semigroup m) => QDiagram b v n m -> QDiagram b v n m Source
"Localize" a diagram by hiding all the names, so they are no longer visible to the outside.
Other
setEnvelope :: forall b v n m. (OrderedField n, Metric v, Monoid' m) => Envelope v n -> QDiagram b v n m -> QDiagram b v n m Source
Replace the envelope of a diagram.
setTrace :: forall b v n m. (OrderedField n, Metric v, Semigroup m) => Trace v n -> QDiagram b v n m -> QDiagram b v n m Source
Replace the trace of a diagram.
Subdiagrams
data Subdiagram b v n m Source
A Subdiagram
represents a diagram embedded within the context
of a larger diagram. Essentially, it consists of a diagram
paired with any accumulated information from the larger context
(transformations, attributes, etc.).
Subdiagram (QDiagram b v n m) (DownAnnots v n) |
Functor (Subdiagram b v n) Source | |
(Metric v, OrderedField n) => HasOrigin (Subdiagram b v n m) Source | |
(Metric v, Floating n) => Transformable (Subdiagram b v n m) Source | |
(OrderedField n, Metric v, Semigroup m) => Traced (Subdiagram b v n m) Source | |
(OrderedField n, Metric v, Monoid' m) => Enveloped (Subdiagram b v n m) Source | |
type N (Subdiagram b v n m) = n Source | |
type V (Subdiagram b v n m) = v Source |
mkSubdiagram :: QDiagram b v n m -> Subdiagram b v n m Source
Turn a diagram into a subdiagram with no accumulated context.
getSub :: (Metric v, OrderedField n, Semigroup m) => Subdiagram b v n m -> QDiagram b v n m Source
Turn a subdiagram into a normal diagram, including the enclosing
context. Concretely, a subdiagram is a pair of (1) a diagram and
(2) a "context" consisting of an extra transformation and
attributes. getSub
simply applies the transformation and
attributes to the diagram to get the corresponding "top-level"
diagram.
rawSub :: Subdiagram b v n m -> QDiagram b v n m Source
Extract the "raw" content of a subdiagram, by throwing away the context.
location :: (Additive v, Num n) => Subdiagram b v n m -> Point v n Source
Get the location of a subdiagram; that is, the location of its local origin with respect to the vector space of its parent diagram. In other words, the point where its local origin "ended up".
subPoint :: (Metric v, OrderedField n, Semigroup m) => Point v n -> Subdiagram b v n m Source
Create a "point subdiagram", that is, a pointDiagram
(with no
content and a point envelope) treated as a subdiagram with local
origin at the given point. Note this is not the same as
mkSubdiagram . pointDiagram
, which would result in a subdiagram
with local origin at the parent origin, rather than at the given
point.
Subdiagram maps
A SubMap
is a map associating names to subdiagrams. There can
be multiple associations for any given name.
SubMap (Map Name [Subdiagram b v n m]) |
Action Name (SubMap b v n m) Source | A name acts on a name map by qualifying every name in it. |
Functor (SubMap b v n) Source | |
Monoid (SubMap b v n m) Source |
|
Semigroup (SubMap b v n m) Source | |
Wrapped (SubMap b v n m) Source | |
(OrderedField n, Metric v) => HasOrigin (SubMap b v n m) Source | |
(Metric v, Floating n) => Transformable (SubMap b v n m) Source | |
Qualifiable (SubMap b v n m) Source |
|
Rewrapped (SubMap b v n m) (SubMap b' v' n' m') Source | |
type Unwrapped (SubMap b v n m) = Map Name [Subdiagram b v n m] Source | |
type N (SubMap b v n m) = n Source | |
type V (SubMap b v n m) = v Source |
fromNames :: IsName a => [(a, Subdiagram b v n m)] -> SubMap b v n m Source
Construct a SubMap
from a list of associations between names
and subdiagrams.
rememberAs :: IsName a => a -> QDiagram b v n m -> SubMap b v n m -> SubMap b v n m Source
Add a name/diagram association to a submap.
lookupSub :: IsName nm => nm -> SubMap b v n m -> Maybe [Subdiagram b v n m] Source
Look for the given name in a name map, returning a list of subdiagrams associated with that name. If no names match the given name exactly, return all the subdiagrams associated with names of which the given name is a suffix.
Primtives
Ultimately, every diagram is essentially a tree whose leaves are primitives,
basic building blocks which can be rendered by backends. However,
not every backend must be able to render every type of primitive;
the collection of primitives a given backend knows how to render is
determined by instances of Renderable
.
A value of type Prim b v n
is an opaque (existentially quantified)
primitive which backend b
knows how to render in vector space v
.
Prim :: (Transformable p, Typeable p, Renderable p b) => p -> Prim b (V p) (N p) |
Transformable (Prim b v n) Source | The |
Renderable (Prim b v n) b Source | The |
type N (Prim b v n) = n Source | |
type V (Prim b v n) = v Source |
_Prim :: (Transformable p, Typeable p, Renderable p b) => Prism' (Prim b (V p) (N p)) p Source
Backends
class Backend b v n where Source
Abstract diagrams are rendered to particular formats by
backends. Each backend/vector space combination must be an
instance of the Backend
class.
A minimal complete definition consists of Render
, Result
,
Options
, and renderRTree
. However, most backends will want to
implement adjustDia
as well; the default definition does
nothing. Some useful standard definitions are provided in the
Diagrams.TwoD.Adjust
module from the diagrams-lib
package.
An intermediate representation used for rendering primitives.
(Typically, this will be some sort of monad, but it need not
be.) The Renderable
class guarantees that a backend will be
able to convert primitives into this type; how these rendered
primitives are combined into an ultimate Result
is completely
up to the backend.
The result of running/interpreting a rendering operation.
data Options b v n :: * Source
Backend-specific rendering options.
adjustDia :: (Additive v, Monoid' m, Num n) => b -> Options b v n -> QDiagram b v n m -> (Options b v n, Transformation v n, QDiagram b v n m) Source
adjustDia
allows the backend to make adjustments to the final
diagram (e.g. to adjust the size based on the options) before
rendering it. It returns a modified options record, the
transformation applied to the diagram (which can be used to
convert attributes whose value is Measure
, or transform
e.g. screen coordinates back into local diagram coordinates),
and the adjusted diagram itself.
See the diagrams-lib package (particularly the
Diagrams.TwoD.Adjust
module) for some useful implementations.
renderRTree :: b -> Options b v n -> RTree b v n Annotation -> Result b v n Source
Given some options, take a representation of a diagram as a
tree and render it. The RTree
has already been simplified
and has all measurements converted to Output
units.
Backend NullBackend v n Source |
DStyle (Style v n) | |
DTransform (Transformation v n) | |
DAnnot a | |
DDelay |
|
DPrim (Prim b v n) | |
DEmpty |
Null backend
data NullBackend Source
A null backend which does no actual rendering. It is provided
mainly for convenience in situations where you must give a
diagram a concrete, monomorphic type, but don't actually care
which one. See D
for more explanation and examples.
It is courteous, when defining a new primitive P
, to make an instance
instance Renderable P NullBackend where render _ _ = mempty
This ensures that the trick with D
annotations can be used for
diagrams containing your primitive.
Backend NullBackend v n Source | |
Monoid (Render NullBackend v n) Source | |
data Render NullBackend = NullBackendRender Source | |
data Options NullBackend Source | |
type Result NullBackend v n = () Source |
type D v n = QDiagram NullBackend v n Any Source
The D
type is provided for convenience in situations where you
must give a diagram a concrete, monomorphic type, but don't care
which one. Such situations arise when you pass a diagram to a
function which is polymorphic in its input but monomorphic in its
output, such as width
, height
, phantom
, or names
. Such
functions compute some property of the diagram, or use it to
accomplish some other purpose, but do not result in the diagram
being rendered. If the diagram does not have a monomorphic type,
GHC complains that it cannot determine the diagram's type.
For example, here is the error we get if we try to compute the
width of an image (this example requires diagrams-lib
):
ghci> width (image (uncheckedImageRef "foo.png" 200 200)) <interactive>:11:8: No instance for (Renderable (DImage n0 External) b0) arising from a use ofimage
The type variablesn0
,b0
are ambiguous Possible fix: add a type signature that fixes these type variable(s) Note: there is a potential instance available: instance Fractional n => Renderable (DImage n a) NullBackend -- Defined inImage
Possible fix: add an instance declaration for (Renderable (DImage n0 External) b0) In the first argument ofwidth
, namely `(image (uncheckedImageRef "foo.png" 200 200))' In the expression: width (image (uncheckedImageRef "foo.png" 200 200)) In an equation forit
: it = width (image (uncheckedImageRef "foo.png" 200 200))
GHC complains that there is no instance for Renderable (DImage n0
External) b0
; what is really going on is that it does not have enough
information to decide what backend to use (hence the
uninstantiated n0
and b0
). This is annoying because we know that the
choice of backend cannot possibly affect the width of the image
(it's 200! it's right there in the code!); but there is no way
for GHC to know that.
The solution is to annotate the call to image
with the type
, like so:D
V2
Double
ghci> width (image (uncheckedImageRef "foo.png" 200 200) :: D V2 Double) 200.00000000000006
(It turns out the width wasn't 200 after all...)
As another example, here is the error we get if we try to compute the width of a radius-1 circle:
ghci> width (circle 1) <interactive>:12:1: Couldn't match expected typeV2
with actual type `V a0' The type variablea0
is ambiguous Possible fix: add a type signature that fixes these type variable(s) In the expression: width (circle 1) In an equation forit
: it = width (circle 1)
There's even more ambiguity here. Whereas image
always returns
a Diagram
, the circle
function can produce any TrailLike
type, and the width
function can consume any Enveloped
type,
so GHC has no idea what type to pick to go in the middle.
However, the solution is the same:
ghci> width (circle 1 :: D V2 Double) 1.9999999999999998
Number classes
class (Typeable n, RealFloat n) => TypeableFloat n Source
(Typeable * n, RealFloat n) => TypeableFloat n Source |
Renderable
class Transformable t => Renderable t b where Source
The Renderable type class connects backends to primitives which they know how to render.
render :: b -> t -> Render b (V t) (N t) Source
Given a token representing the backend and a transformable object, render it in the appropriate rendering context.
Renderable (Prim b v n) b Source | The |