diagrams-lib-1.2: src/Diagrams/Coordinates.hs
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
-----------------------------------------------------------------------------
-- |
-- Module : Diagrams.Coordinates
-- Copyright : (c) 2012 diagrams-lib team (see LICENSE)
-- License : BSD-style (see LICENSE)
-- Maintainer : diagrams-discuss@googlegroups.com
--
-- Nice syntax for constructing and pattern-matching on literal
-- points and vectors.
--
-----------------------------------------------------------------------------
module Diagrams.Coordinates
( (:&)(..), Coordinates(..)
-- * Lenses for particular axes
, HasX(..), HasY(..), HasZ(..), HasR(..)
)
where
import Control.Lens (Lens')
import Diagrams.Core.Points
-- | A pair of values, with a convenient infix (left-associative)
-- data constructor.
data a :& b = a :& b
deriving (Eq, Ord, Show)
infixl 7 :&
-- | Types which are instances of the @Coordinates@ class can be
-- constructed using '^&' (for example, a three-dimensional vector
-- could be constructed by @1 ^& 6 ^& 3@), and deconstructed using
-- 'coords'. A common pattern is to use 'coords' in conjunction
-- with the @ViewPatterns@ extension, like so:
--
-- @
-- foo :: Vector3 -> ...
-- foo (coords -> x :& y :& z) = ...
-- @
class Coordinates c where
-- | The type of the final coordinate.
type FinalCoord c :: *
-- | The type of everything other than the final coordinate.
type PrevDim c :: *
-- | Decomposition of @c@ into applications of ':&'.
type Decomposition c :: *
-- Decomposition c = Decomposition (PrevDim c) :& FinalCoord c (essentially)
-- | Construct a value of type @c@ by providing something of one
-- less dimension (which is perhaps itself recursively constructed
-- using @(^&)@) and a final coordinate. For example,
--
-- @
-- 2 ^& 3 :: P2
-- 3 ^& 5 ^& 6 :: R3
-- @
--
-- Note that @^&@ is left-associative.
(^&) :: PrevDim c -> FinalCoord c -> c
-- | Prefix synonym for @^&@. pr stands for pair of @PrevDim@, @FinalCoord@
pr :: PrevDim c -> FinalCoord c -> c
pr = (^&)
-- | Decompose a value of type @c@ into its constituent coordinates,
-- stored in a nested @(:&)@ structure.
coords :: c -> Decomposition c
infixl 7 ^&
-- Some standard instances for plain old tuples
instance Coordinates (a,b) where
type FinalCoord (a,b) = b
type PrevDim (a,b) = a
type Decomposition (a,b) = a :& b
x ^& y = (x,y)
coords (x,y) = x :& y
instance Coordinates (a,b,c) where
type FinalCoord (a,b,c) = c
type PrevDim (a,b,c) = (a,b)
type Decomposition (a,b,c) = Decomposition (a,b) :& c
(x,y) ^& z = (x,y,z)
coords (x,y,z) = coords (x,y) :& z
instance Coordinates (a,b,c,d) where
type FinalCoord (a,b,c,d) = d
type PrevDim (a,b,c,d) = (a,b,c)
type Decomposition (a,b,c,d) = Decomposition (a,b,c) :& d
(w,x,y) ^& z = (w,x,y,z)
coords (w,x,y,z) = coords (w,x,y) :& z
instance Coordinates v => Coordinates (Point v) where
type FinalCoord (Point v) = FinalCoord v
type PrevDim (Point v) = PrevDim v
type Decomposition (Point v) = Decomposition v
x ^& y = P (x ^& y)
coords (P v) = coords v
-- | The class of types with at least one coordinate, called _x.
class HasX t where
_x :: Lens' t Double
-- | The class of types with at least two coordinates, the second called _y.
class HasY t where
_y :: Lens' t Double
-- | The class of types with at least three coordinates, the third called _z.
class HasZ t where
_z :: Lens' t Double
-- | The class of types with a single length coordinate _r. _r is
-- magnitude of a vector, or the distance from the origin of a point.
class HasR t where
_r :: Lens' t Double