{-# 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, -- . 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)