diagrams-core-1.4: src/Diagrams/Core/Query.hs
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
{-# OPTIONS_GHC -fno-warn-unused-imports #-}
-----------------------------------------------------------------------------
-- |
-- Module : Diagrams.Core.Query
-- Copyright : (c) 2011-2015 diagrams-core team (see LICENSE)
-- License : BSD-style (see LICENSE)
-- Maintainer : diagrams-discuss@googlegroups.com
--
-- The @Query@ module defines a type for \"queries\" on diagrams, which
-- are functions from points in a vector space to some monoid.
--
-----------------------------------------------------------------------------
module Diagrams.Core.Query
( Query (..)
) where
import Control.Applicative
import Control.Lens
import Data.Semigroup
import Data.Distributive
import Data.Functor.Rep
import Data.Profunctor
import Data.Profunctor.Sieve
import Data.Profunctor.Closed
import qualified Data.Profunctor.Rep as P
import Linear.Affine
import Linear.Vector
import Diagrams.Core.HasOrigin
import Diagrams.Core.Transform
import Diagrams.Core.V
------------------------------------------------------------------------
-- Queries
------------------------------------------------------------------------
-- | A query is a function that maps points in a vector space to
-- values in some monoid. Queries naturally form a monoid, with
-- two queries being combined pointwise.
--
-- The idea for annotating diagrams with monoidal queries came from
-- the graphics-drawingcombinators package,
-- <http://hackage.haskell.org/package/graphics-drawingcombinators>.
newtype Query v n m = Query { runQuery :: Point v n -> m }
deriving (Functor, Applicative, Monad, Semigroup, Monoid)
instance Distributive (Query v n) where
distribute a = Query $ \p -> fmap (\(Query q) -> q p) a
instance Representable (Query v n) where
type Rep (Query v n) = Point v n
tabulate = Query
index = runQuery
instance Functor v => Profunctor (Query v) where
lmap f (Query q) = Query $ \p -> q (fmap f p)
rmap = fmap
instance Functor v => Cosieve (Query v) (Point v) where
cosieve = runQuery
instance Functor v => Closed (Query v) where
closed (Query fab) = Query $ \fxa x -> fab (fmap ($ x) fxa)
instance Functor v => Costrong (Query v) where
unfirst (Query f) = Query f'
where f' fa = b where (b, d) = f ((\a -> (a, d)) <$> fa)
unsecond (Query f) = Query f'
where f' fa = b where (d, b) = f ((,) d <$> fa)
instance Functor v => P.Corepresentable (Query v) where
type Corep (Query v) = Point v
cotabulate = Query
-- | Setter over the input point of a query.
queryPoint :: Setter (Query v' n' m) (Query v n m) (Point v n) (Point v' n')
queryPoint = sets $ \f (Query q) -> Query $ q . f
instance Wrapped (Query v n m) where
type Unwrapped (Query v n m) = Point v n -> m
_Wrapped' = iso runQuery Query
instance Rewrapped (Query v a m) (Query v' a' m')
type instance V (Query v n m) = v
type instance N (Query v n m) = n
instance (Additive v, Num n) => HasOrigin (Query v n m) where
moveOriginTo (P u) = queryPoint %~ (.+^ u)
instance (Additive v, Num n) => Transformable (Query v n m) where
transform t = queryPoint %~ papply (inv t)