----------------------------------------------------------------------------- -- | -- Module : Diagrams.Util -- Copyright : (c) 2011 diagrams-lib team (see LICENSE) -- License : BSD-style (see LICENSE) -- Maintainer : diagrams-discuss@googlegroups.com -- -- Some miscellaneous utilities provided by the diagrams-lib package. -- ----------------------------------------------------------------------------- module Diagrams.Util ( -- * Utilities for users with , (<>) , applyAll , (#) -- * Internal utilities , Proxy(..) ) where import Data.Monoid import Data.Default -- | Several functions exported by the diagrams library take a number -- of arguments giving the user control to \"tweak\" various aspects -- of their behavior. Rather than give such functions a long list -- of arguments, and to make it possible for the user to selectively -- override only certain arguments and use default values for -- others, such sets of arguments are collected into a record with -- named fields (see 'PolygonOpts' in "Diagrams.TwoD.Shapes" for an -- example). Such record types are made instances of the 'Default' -- class, which provides a single record structure ('def') -- collecting the \"default\" arguments to the function. @with@ is -- a synonym for 'def', which provides nice-looking syntax for -- simulating optional, named arguments in Haskell. For example, -- -- > polygon with {sides = 7, edgeSkip = 2} -- -- calls the 'polygon' function with a single argument (note that -- record update binds more tightly than function application!), -- namely, 'with' (the record of default arguments) where the -- @sides@ and @edgeSkip@ fields have been updated. with :: Default d => d with = def -- | A convenient infix operator for 'mappend' (monoidal combination). -- Many things in the diagrams library can be combined using @(\<\>)@, -- with the meaning dependent on the types of things being combined. -- For example: -- -- * The combination of two transformations @t1 \<\> t2@ is a -- transformation which performs first @t2@, then @t1@. -- -- * Combining two diagrams @d1 \<\> d2@ results in a superimposed -- diagram with @d1@ on top of @d2@ (with their local origins aligned). -- -- * Combining two paths works in the same way as combining diagrams. -- -- * Combining two trails results in a longer trail composed of the -- first trail followed by the second. -- -- * Combining two styles, @s1 \<\> s2@, results in a style with -- combined attributes from both, biased to @s2@ when @s1@ and -- @s2@ contain attributes of the same type. -- -- * Combining two @'AlphaColour' Double@s results in a composited -- color (the color that results when objects of the two colors are -- superimposed). -- -- In addition, 'mempty' always represents a suitably \"trivial\" -- object which is the identity for @(\<\>)@ (that is, @mempty \<\> -- x == x \<\> mempty == x@). 'mempty' can stand for the identity -- transformation; the empty diagram, path, trail, or style; the -- completely transparent color; and so on. (<>) :: Monoid m => m -> m -> m (<>) = mappend infixr 5 <> -- | @applyAll@ takes a list of functions and applies them all to a -- value, in sequence from the last function in the list to the first. -- For example, @applyAll [f1, f2, f3] a == f1 . f2 . f3 $ a@. applyAll :: [a -> a] -> a -> a applyAll = appEndo . mconcat . map Endo infixl 8 # -- | Postfix function application, for conveniently applying -- attributes. Unlike @($)@, @(#)@ has a high precedence (8), so @d -- \# foo \# bar@ can be combined with other things using operators -- like @(|||)@ or @(\<\>)@ without needing parentheses. (#) :: a -> (a -> b) -> b (#) = flip ($) -- | A value of @Proxy a@ carries no information; it's used only to -- fix the type @a@. data Proxy a = Proxy