-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Abstractions for animation -- -- Active abstraction for animated things with finite start and -- end times. @package active @version 0.2.0.8 -- | Inspired by the work of Kevin Matlage and Andy Gill (Every -- Animation Should Have a Beginning, a Middle, and an End, Trends -- in Functional Programming, 2010. -- http://ittc.ku.edu/csdl/fpg/node/46), this module defines a -- simple abstraction for working with time-varying values. A value of -- type Active a is either a constant value of type a, -- or a time-varying value of type a (i.e. a function -- from time to a) with specific start and end times. Since -- active values have start and end times, they can be aligned, -- sequenced, stretched, or reversed. -- -- In a sense, this is sort of like a stripped-down version of functional -- reactive programming (FRP), without the reactivity. -- -- The original motivating use for this library is to support making -- animations with the diagrams framework -- (http://projects.haskell.org/diagrams), but the hope is that it -- may find more general utility. -- -- There are two basic ways to create an Active value. The first -- is to use mkActive to create one directly, by specifying a -- start and end time and a function of time. More indirectly, one can -- use the Applicative instance together with the unit interval -- ui, which takes on values from the unit interval from time 0 to -- time 1, or interval, which creates an active over an arbitrary -- interval. -- -- For example, to create a value of type Active Double which -- represents one period of a sine wave starting at time 0 and ending at -- time 1, we could write -- --
--   mkActive 0 1 (\t -> sin (fromTime t * tau))
--   
-- -- or -- --
--   (sin . (*tau)) <$> ui
--   
-- -- pure can also be used to create Active values which -- are constant and have no start or end time. For example, -- --
--   mod <$> (floor <$> interval 0 100) <*> pure 7
--   
-- -- cycles repeatedly through the numbers 0-6. -- -- Note that the "idiom bracket" notation supported by the SHE -- preprocessor (http://personal.cis.strath.ac.uk/~conor/pub/she/, -- http://hackage.haskell.org/package/she) can make for somewhat -- more readable Applicative code. For example, the above example -- can be rewritten using SHE as -- --
--   {-# OPTIONS_GHC -F -pgmF she #-}
--   
--   ... (| mod (| floor (interval 0 100) |) ~7 |)
--   
-- -- There are many functions for transforming and composing active values; -- see the documentation below for more details. -- -- With careful handling, this module should be suitable to generating -- deep embeddings if Active values. module Data.Active -- | An abstract type for representing points in time. Note that -- literal numeric values may be used as Times, thanks to the -- the Num and Fractional instances. data Time n -- | A convenient wrapper function to convert a numeric value into a time. toTime :: n -> Time n -- | A convenient unwrapper function to turn a time into a numeric value. fromTime :: Time n -> n -- | An abstract type representing elapsed time between two points -- in time. Note that durations can be negative. Literal numeric values -- may be used as Durations thanks to the Num and -- Fractional instances. data Duration n -- | A convenient wrapper function to convert a numeric value into a -- duration. toDuration :: n -> Duration n -- | A convenient unwrapper function to turn a duration into a numeric -- value. fromDuration :: Duration n -> n -- | An Era is a concrete span of time, that is, a pair of times -- representing the start and end of the era. Eras form a -- semigroup: the combination of two Eras is the smallest -- Era which contains both. They do not form a Monoid, -- since there is no Era which acts as the identity with respect -- to this combining operation. -- -- Era is abstract. To construct Era values, use -- mkEra; to deconstruct, use start and end. data Era n -- | Create an Era by specifying start and end Times. mkEra :: Time n -> Time n -> Era n -- | Get the start Time of an Era. start :: Era n -> Time n -- | Get the end Time of an Era. end :: Era n -> Time n -- | Compute the Duration of an Era. duration :: Num n => Era n -> Duration n -- | A Dynamic a can be thought of as an a value that -- changes over the course of a particular Era. It's envisioned -- that Dynamic will be mostly an internal implementation detail -- and that Active will be most commonly used. But you never know -- what uses people might find for things. data Dynamic a Dynamic :: Era Rational -> (Time Rational -> a) -> Dynamic a [era] :: Dynamic a -> Era Rational [runDynamic] :: Dynamic a -> Time Rational -> a -- | Create a Dynamic from a start time, an end time, and a -- time-varying value. mkDynamic :: Time Rational -> Time Rational -> (Time Rational -> a) -> Dynamic a -- | Fold for Dynamic. onDynamic :: (Time Rational -> Time Rational -> (Time Rational -> a) -> b) -> Dynamic a -> b -- | Shift a Dynamic value by a certain duration. shiftDynamic :: Duration Rational -> Dynamic a -> Dynamic a -- | There are two types of Active values: -- -- -- -- The addition of constant values enable Monoid and -- Applicative instances for Active. data Active a -- | Create a dynamic Active from a start time, an end time, and a -- time-varying value. mkActive :: Time Rational -> Time Rational -> (Time Rational -> a) -> Active a -- | Create an Active value from a Dynamic. fromDynamic :: Dynamic a -> Active a -- | Test whether an Active value is constant. isConstant :: Active a -> Bool -- | Test whether an Active value is Dynamic. isDynamic :: Active a -> Bool -- | Fold for Actives. Process an 'Active a', given a function to -- apply if it is a pure (constant) value, and a function to apply if it -- is a Dynamic. onActive :: (a -> b) -> (Dynamic a -> b) -> Active a -> b -- | Modify an Active value using a case analysis to see whether it -- is constant or dynamic. modActive :: (a -> b) -> (Dynamic a -> Dynamic b) -> Active a -> Active b -- | Interpret an Active value as a function from time. runActive :: Active a -> Time Rational -> a -- | Get the Era of an Active value (or Nothing if it -- is a constant/pure value). activeEra :: Active a -> Maybe (Era Rational) -- | Set the era of an Active value. Note that this will change a -- constant Active into a dynamic one which happens to have the -- same value at all times. setEra :: Era Rational -> Active a -> Active a -- | atTime t a is an active value with the same behavior as -- a, shifted so that it starts at time t. If -- a is constant it is returned unchanged. atTime :: Time Rational -> Active a -> Active a -- | Get the value of an Active a at the beginning of its era. activeStart :: Active a -> a -- | Get the value of an Active a at the end of its era. activeEnd :: Active a -> a -- | ui represents the unit interval, which takes on the -- value t at time t, and has as its era -- [0,1]. It is equivalent to interval 0 1, and -- can be visualized as follows: -- -- -- On the x-axis is time, and the value that ui takes on is on -- the y-axis. The shaded portion represents the era. Note that the value -- of ui (as with any active) is still defined outside its era, -- and this can make a difference when it is combined with other active -- values with different eras. Applying a function with fmap -- affects all values, both inside and outside the era. To manipulate -- values outside the era specifically, see clamp and trim. -- -- To alter the values that ui takes on without altering -- its era, use its Functor and Applicative instances. For -- example, (*2) <$> ui varies from 0 to -- 2 over the era [0,1]. To alter the era, you can use -- stretch or shift. ui :: Fractional a => Active a -- | interval a b is an active value starting at time a, -- ending at time b, and taking the value t at time -- t. interval :: Fractional a => Time Rational -> Time Rational -> Active a -- | stretch s act "stretches" the active act so that it -- takes s times as long (retaining the same start time). stretch :: Rational -> Active a -> Active a -- | stretchTo d stretches an Active so it has -- duration d. Has no effect if (1) d is non-positive, -- or (2) the Active value is constant, or (3) the Active -- value has zero duration. [AJG: conditions (1) and (3) no longer true: -- to consider changing] stretchTo :: Duration Rational -> Active a -> Active a -- | a1 `during` a2 stretches and shifts a1 -- so that it has the same era as a2. Has no effect if either of -- a1 or a2 are constant. during :: Active a -> Active a -> Active a -- | shift d act shifts the start time of act by duration -- d. Has no effect on constant values. shift :: Duration Rational -> Active a -> Active a -- | Reverse an active value so the start of its era gets mapped to the end -- and vice versa. For example, backwards ui can be -- visualized as -- backwards :: Active a -> Active a -- | Take a "snapshot" of an active value at a particular time, resulting -- in a constant value. snapshot :: Time Rational -> Active a -> Active a -- | "Clamp" an active value so that it is constant before and after its -- era. Before the era, clamp a takes on the value of a -- at the start of the era. Likewise, after the era, clamp a -- takes on the value of a at the end of the era. clamp -- has no effect on constant values. -- -- For example, clamp ui can be visualized as -- -- -- See also clampBefore and clampAfter, which clamp only -- before or after the era, respectively. clamp :: Active a -> Active a -- | "Clamp" an active value so that it is constant before the start of its -- era. For example, clampBefore ui can be visualized as -- -- -- See the documentation of clamp for more information. clampBefore :: Active a -> Active a -- | "Clamp" an active value so that it is constant after the end of its -- era. For example, clampBefore ui can be visualized as -- -- -- See the documentation of clamp for more information. clampAfter :: Active a -> Active a -- | "Trim" an active value so that it is empty outside its era. -- trim has no effect on constant values. -- -- For example, trim ui can be visualized as -- -- -- Actually, trim ui is not well-typed, since it is not -- guaranteed that ui's values will be monoidal (and usually -- they won't be)! But the above image still provides a good intuitive -- idea of what trim is doing. To make this precise we could -- consider something like trim (First . Just $ ui). -- -- See also trimBefore and trimActive, which trim only -- before or after the era, respectively. trim :: Monoid a => Active a -> Active a -- | "Trim" an active value so that it is empty before the start of -- its era. For example, trimBefore ui can be visualized -- as -- -- -- See the documentation of trim for more details. trimBefore :: Monoid a => Active a -> Active a -- | "Trim" an active value so that it is empty after the end of its -- era. For example, trimAfter ui can be visualized as -- -- -- See the documentation of trim for more details. trimAfter :: Monoid a => Active a -> Active a -- | a1 `after` a2 produces an active that behaves like -- a1 but is shifted to start at the end time of a2. If -- either a1 or a2 are constant, a1 is -- returned unchanged. after :: Active a -> Active a -> Active a -- | Sequence/overlay two Active values: shift the second to start -- immediately after the first (using after), then compose them -- (using <>). (->>) :: Semigroup a => Active a -> Active a -> Active a -- | "Splice" two Active values together: shift the second to start -- immediately after the first (using after), and produce the -- value which acts like the first up to the common end/start point, then -- like the second after that. If both are constant, return the first. (|>>) :: Active a -> Active a -> Active a -- | Splice together a list of active values using |>>. The -- list must be nonempty. movie :: [Active a] -> Active a -- | Create an Active which takes on each value in the given list -- in turn during the time [0,1], with each value getting an -- equal amount of time. In other words, discrete creates a -- "slide show" that starts at time 0 and ends at time 1. The first -- element is used prior to time 0, and the last element is used after -- time 1. -- -- It is an error to call discrete on the empty list. discrete :: [a] -> Active a -- | simulate r act simulates the Active value -- act, returning a list of "snapshots" taken at regular -- intervals from the start time to the end time. The interval used is -- determined by the rate r, which denotes the "frame rate", -- that is, the number of snapshots per unit time. -- -- If the Active value is constant (and thus has no start or end -- times), a list of length 1 is returned, containing the constant value. simulate :: Rational -> Active a -> [a] instance (Data.Functor.Bind.Class.MaybeApply f1 a1 ~ t0) => Control.Lens.Wrapped.Rewrapped (Data.Functor.Bind.Class.MaybeApply f0 a0) t0 instance Control.Lens.Wrapped.Wrapped (Data.Functor.Bind.Class.MaybeApply f0 a0) instance Data.Semigroup.Semigroup a => Data.Semigroup.Semigroup (Data.Active.Active a) instance (GHC.Base.Monoid a, Data.Semigroup.Semigroup a) => GHC.Base.Monoid (Data.Active.Active a) instance (Data.Active.Active a1 ~ t0) => Control.Lens.Wrapped.Rewrapped (Data.Active.Active a0) t0 instance Control.Lens.Wrapped.Wrapped (Data.Active.Active a0) instance GHC.Base.Applicative Data.Active.Active instance Data.Functor.Bind.Class.Apply Data.Active.Active instance GHC.Base.Functor Data.Active.Active instance GHC.Base.Functor Data.Active.Dynamic instance GHC.Classes.Ord n => Data.Semigroup.Semigroup (Data.Active.Era n) instance GHC.Show.Show n => GHC.Show.Show (Data.Active.Era n) instance (Data.Active.Duration n1 ~ t0) => Control.Lens.Wrapped.Rewrapped (Data.Active.Duration n0) t0 instance Control.Lens.Wrapped.Wrapped (Data.Active.Duration n0) instance GHC.Base.Applicative Data.Active.Duration instance Linear.Vector.Additive Data.Active.Duration instance GHC.Num.Num n => Data.Semigroup.Semigroup (Data.Active.Duration n) instance GHC.Num.Num n => GHC.Base.Monoid (Data.Active.Duration n) instance Data.Functor.Bind.Class.Apply Data.Active.Dynamic instance Data.Semigroup.Semigroup a => Data.Semigroup.Semigroup (Data.Active.Dynamic a) instance GHC.Base.Functor Data.Active.Duration instance GHC.Real.RealFrac n => GHC.Real.RealFrac (Data.Active.Duration n) instance GHC.Real.Real n => GHC.Real.Real (Data.Active.Duration n) instance GHC.Real.Fractional n => GHC.Real.Fractional (Data.Active.Duration n) instance GHC.Num.Num n => GHC.Num.Num (Data.Active.Duration n) instance GHC.Enum.Enum n => GHC.Enum.Enum (Data.Active.Duration n) instance GHC.Read.Read n => GHC.Read.Read (Data.Active.Duration n) instance GHC.Show.Show n => GHC.Show.Show (Data.Active.Duration n) instance GHC.Classes.Ord n => GHC.Classes.Ord (Data.Active.Duration n) instance GHC.Classes.Eq n => GHC.Classes.Eq (Data.Active.Duration n) instance (Data.Active.Time n1 ~ t0) => Control.Lens.Wrapped.Rewrapped (Data.Active.Time n0) t0 instance Control.Lens.Wrapped.Wrapped (Data.Active.Time n0) instance Linear.Affine.Affine Data.Active.Time instance GHC.Base.Functor Data.Active.Time instance GHC.Real.RealFrac n => GHC.Real.RealFrac (Data.Active.Time n) instance GHC.Real.Real n => GHC.Real.Real (Data.Active.Time n) instance GHC.Real.Fractional n => GHC.Real.Fractional (Data.Active.Time n) instance GHC.Num.Num n => GHC.Num.Num (Data.Active.Time n) instance GHC.Enum.Enum n => GHC.Enum.Enum (Data.Active.Time n) instance GHC.Read.Read n => GHC.Read.Read (Data.Active.Time n) instance GHC.Show.Show n => GHC.Show.Show (Data.Active.Time n) instance GHC.Classes.Ord n => GHC.Classes.Ord (Data.Active.Time n) instance GHC.Classes.Eq n => GHC.Classes.Eq (Data.Active.Time n)