packages feed

active 0.1.0.19 → 0.2.0.0

raw patch · 5 files changed

+179/−161 lines, 5 filesdep +lensdep +lineardep +vectordep −arraydep −newtypedep −vector-spacedep ~semigroupoidsPVP ok

version bump matches the API change (PVP)

Dependencies added: lens, linear, vector

Dependencies removed: array, newtype, vector-space

Dependency ranges changed: semigroupoids

API changes (from Hackage documentation)

- Data.Active: fromDuration :: Fractional a => Duration -> a
- Data.Active: fromTime :: Fractional a => Time -> a
- Data.Active: instance AdditiveGroup Duration
- Data.Active: instance AdditiveGroup Time
- Data.Active: instance AffineSpace Time
- Data.Active: instance Enum Duration
- Data.Active: instance Enum Time
- Data.Active: instance Eq Duration
- Data.Active: instance Eq Time
- Data.Active: instance Fractional Duration
- Data.Active: instance Fractional Time
- Data.Active: instance InnerSpace Time
- Data.Active: instance Newtype (Active a) (MaybeApply Dynamic a)
- Data.Active: instance Newtype (MaybeApply f a) (Either (f a) a)
- Data.Active: instance Newtype Duration Rational
- Data.Active: instance Newtype Time Rational
- Data.Active: instance Num Duration
- Data.Active: instance Num Time
- Data.Active: instance Ord Duration
- Data.Active: instance Ord Time
- Data.Active: instance Read Duration
- Data.Active: instance Read Time
- Data.Active: instance Real Duration
- Data.Active: instance Real Time
- Data.Active: instance RealFrac Duration
- Data.Active: instance RealFrac Time
- Data.Active: instance Semigroup Era
- Data.Active: instance Show Duration
- Data.Active: instance Show Era
- Data.Active: instance Show Time
- Data.Active: instance VectorSpace Duration
- Data.Active: instance VectorSpace Time
- Data.Active: toDuration :: Real a => a -> Duration
- Data.Active: toTime :: Real a => a -> Time
+ Data.Active: instance Active a1 ~ t0 => Rewrapped (Active a0) t0
+ Data.Active: instance Additive Duration
+ Data.Active: instance Affine Time
+ Data.Active: instance Applicative Duration
+ Data.Active: instance Duration n1 ~ t0 => Rewrapped (Duration n0) t0
+ Data.Active: instance Enum n => Enum (Duration n)
+ Data.Active: instance Enum n => Enum (Time n)
+ Data.Active: instance Eq n => Eq (Duration n)
+ Data.Active: instance Eq n => Eq (Time n)
+ Data.Active: instance Fractional n => Fractional (Duration n)
+ Data.Active: instance Fractional n => Fractional (Time n)
+ Data.Active: instance Functor Duration
+ Data.Active: instance Functor Time
+ Data.Active: instance MaybeApply f1 a1 ~ t0 => Rewrapped (MaybeApply f0 a0) t0
+ Data.Active: instance Num n => Monoid (Duration n)
+ Data.Active: instance Num n => Num (Duration n)
+ Data.Active: instance Num n => Num (Time n)
+ Data.Active: instance Num n => Semigroup (Duration n)
+ Data.Active: instance Ord n => Ord (Duration n)
+ Data.Active: instance Ord n => Ord (Time n)
+ Data.Active: instance Ord n => Semigroup (Era n)
+ Data.Active: instance Read n => Read (Duration n)
+ Data.Active: instance Read n => Read (Time n)
+ Data.Active: instance Real n => Real (Duration n)
+ Data.Active: instance Real n => Real (Time n)
+ Data.Active: instance RealFrac n => RealFrac (Duration n)
+ Data.Active: instance RealFrac n => RealFrac (Time n)
+ Data.Active: instance Show n => Show (Duration n)
+ Data.Active: instance Show n => Show (Era n)
+ Data.Active: instance Show n => Show (Time n)
+ Data.Active: instance Time n1 ~ t0 => Rewrapped (Time n0) t0
+ Data.Active: instance Wrapped (Active a0)
+ Data.Active: instance Wrapped (Duration n0)
+ Data.Active: instance Wrapped (MaybeApply f0 a0)
+ Data.Active: instance Wrapped (Time n0)
- Data.Active: Dynamic :: Era -> (Time -> a) -> Dynamic a
+ Data.Active: Dynamic :: Era Rational -> (Time Rational -> a) -> Dynamic a
- Data.Active: activeEra :: Active a -> Maybe Era
+ Data.Active: activeEra :: Active a -> Maybe (Era Rational)
- Data.Active: atTime :: Time -> Active a -> Active a
+ Data.Active: atTime :: Time Rational -> Active a -> Active a
- Data.Active: data Duration
+ Data.Active: data Duration n
- Data.Active: data Era
+ Data.Active: data Era n
- Data.Active: data Time
+ Data.Active: data Time n
- Data.Active: duration :: Era -> Duration
+ Data.Active: duration :: Num n => Era n -> Duration n
- Data.Active: end :: Era -> Time
+ Data.Active: end :: Era n -> Time n
- Data.Active: era :: Dynamic a -> Era
+ Data.Active: era :: Dynamic a -> Era Rational
- Data.Active: interval :: Fractional a => Time -> Time -> Active a
+ Data.Active: interval :: Fractional a => Time Rational -> Time Rational -> Active a
- Data.Active: mkActive :: Time -> Time -> (Time -> a) -> Active a
+ Data.Active: mkActive :: Time Rational -> Time Rational -> (Time Rational -> a) -> Active a
- Data.Active: mkDynamic :: Time -> Time -> (Time -> a) -> Dynamic a
+ Data.Active: mkDynamic :: Time Rational -> Time Rational -> (Time Rational -> a) -> Dynamic a
- Data.Active: mkEra :: Time -> Time -> Era
+ Data.Active: mkEra :: Time n -> Time n -> Era n
- Data.Active: onDynamic :: (Time -> Time -> (Time -> a) -> b) -> Dynamic a -> b
+ Data.Active: onDynamic :: (Time Rational -> Time Rational -> (Time Rational -> a) -> b) -> Dynamic a -> b
- Data.Active: runActive :: Active a -> (Time -> a)
+ Data.Active: runActive :: Active a -> Time Rational -> a
- Data.Active: runDynamic :: Dynamic a -> Time -> a
+ Data.Active: runDynamic :: Dynamic a -> Time Rational -> a
- Data.Active: setEra :: Era -> Active a -> Active a
+ Data.Active: setEra :: Era Rational -> Active a -> Active a
- Data.Active: shift :: Duration -> Active a -> Active a
+ Data.Active: shift :: Duration Rational -> Active a -> Active a
- Data.Active: shiftDynamic :: Duration -> Dynamic a -> Dynamic a
+ Data.Active: shiftDynamic :: Duration Rational -> Dynamic a -> Dynamic a
- Data.Active: snapshot :: Time -> Active a -> Active a
+ Data.Active: snapshot :: Time Rational -> Active a -> Active a
- Data.Active: start :: Era -> Time
+ Data.Active: start :: Era n -> Time n
- Data.Active: stretchTo :: Duration -> Active a -> Active a
+ Data.Active: stretchTo :: Duration Rational -> Active a -> Active a

Files

CHANGES view
@@ -1,7 +1,9 @@-0.1.0.19 (2 April 2015)-----------------------+0.2.0.0 (19 April 2015)+----------------------- - - allow `vector-space-0.10`+- switch from `vector-space` to `linear`+- allow `lens-4.9`+- allow `base-4.8`  0.1.0.18 (22 Feb 2015) ----------------------@@ -12,7 +14,7 @@ 0.1.0.17 (03 Dec 2014) ---------------------- - * Allow `semigroups-0.16`+- Allow `semigroups-0.16`  0.1.0.16 (2 June 2014) ----------------------
LICENSE view
@@ -1,4 +1,12 @@-Copyright (c) 2011-2012, Brent Yorgey+Copyright (c) 2011-2015, active team:++Andy Gill <andygill@ku.edu>+Ben Gamari <ben@smart-cactus.org>+Brent Yorgey <byorgey@gmail.com>+Christopher Chalmers <c.chalmers@me.com>+Daniel Bergey <bergey@alum.mit.edu>+Jeffrey Rosenbluth <jeffrey.rosenbluth@gmail.com>+Ryan Scott <ryan.gl.scott@ku.edu>  All rights reserved. 
active.cabal view
@@ -1,17 +1,17 @@ name:                active-version:             0.1.0.19+version:             0.2.0.0 synopsis:            Abstractions for animation description:         "Active" abstraction for animated things with finite start and end times. license:             BSD3 license-file:        LICENSE author:              Brent Yorgey maintainer:          byorgey@cis.upenn.edu-copyright:           (c) 2011 Brent Yorgey+copyright:           (c) 2011-2015 Brent Yorgey category:            Data build-type:          Simple cabal-version:       >=1.10 extra-source-files:  CHANGES-tested-with:         GHC == 6.12.3, GHC == 7.0.4, GHC == 7.2.1, GHC == 7.4.1, GHC == 7.6.1+tested-with:         GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.1 bug-reports:         https://github.com/diagrams/active/issues source-repository head   type:     git@@ -20,11 +20,11 @@ library   exposed-modules:     Data.Active   build-depends:       base >= 4.0 && < 4.9,-                       array >= 0.3 && < 0.6,+                       vector >= 0.10,                        semigroups >= 0.1 && < 0.17,-                       semigroupoids >= 1.2 && < 4.4,-                       vector-space >= 0.8 && < 0.11,-                       newtype >= 0.2 && < 0.3+                       semigroupoids >= 1.2 && < 5.0,+                       lens >= 4.0 && < 4.10,+                       linear >= 1.14 && < 1.19   hs-source-dirs:      src   default-language:    Haskell2010 @@ -32,12 +32,11 @@     type:              exitcode-stdio-1.0     main-is:           active-tests.hs     build-depends:     base >= 4.0 && < 4.9,-                       array >= 0.3 && < 0.6,+                       vector >= 0.10,                        semigroups >= 0.1 && < 0.17,-                       semigroupoids >= 1.2 && < 4.4,-                       vector-space >= 0.8 && < 0.11,-                       newtype >= 0.2 && < 0.3,-+                       semigroupoids >= 1.2 && < 5.0,+                       lens >= 4.0 && < 4.9,+                       linear >= 1.14 && < 1.19,                        QuickCheck >= 2.4.2 && < 2.8     hs-source-dirs:    src, test     default-language:  Haskell2010
src/Data/Active.hs view
@@ -1,10 +1,16 @@-{-# LANGUAGE DeriveFunctor-           , GeneralizedNewtypeDeriving-           , TypeSynonymInstances-           , MultiParamTypeClasses-           , TypeFamilies-           , FlexibleInstances-  #-}+{-# LANGUAGE CPP                        #-}+{-# LANGUAGE DeriveFunctor              #-}+{-# LANGUAGE FlexibleContexts           #-}+{-# LANGUAGE FlexibleInstances          #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses      #-}+{-# LANGUAGE ScopedTypeVariables        #-}+{-# LANGUAGE TemplateHaskell            #-}+{-# LANGUAGE TypeFamilies               #-}+{-# LANGUAGE TypeSynonymInstances       #-}+{-# LANGUAGE ViewPatterns               #-}+{-# LANGUAGE UndecidableInstances       #-}+-- UndecidableInstances needed for ghc < 707 {-# OPTIONS_GHC -fno-warn-orphans #-}  -----------------------------------------------------------------------------@@ -70,6 +76,10 @@ -- 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@@ -77,8 +87,8 @@           -- ** Time and duration -         Time, toTime, fromTime-       , Duration, toDuration, fromDuration+         Time+       , Duration           -- ** Eras @@ -132,21 +142,23 @@         ) where -import Control.Applicative-import Control.Arrow ((&&&))-import Control.Newtype+#if __GLASGOW_HASKELL__ < 710+import           Control.Applicative+#endif -import Data.Array-import Data.Maybe+import           Control.Arrow       ((&&&))+import           Control.Lens        hiding (backwards, (<.>)) -import Data.Functor.Apply-import Data.Semigroup hiding (First(..))-import Data.Monoid (First(..))+import           Data.Functor.Apply+import           Data.Semigroup      hiding (First (..))+import           Data.Monoid         (First (..))+import qualified Data.Vector         as V+import           Data.Maybe -import Data.VectorSpace hiding ((<.>))-import qualified Data.VectorSpace as VS-import Data.AffineSpace+import           Linear+import           Linear.Affine + ------------------------------------------------------------ -- Time ------------------------------------------------------------@@ -156,31 +168,19 @@ --   'Num' and 'Fractional' instances.  'toTime' and 'fromTime' are --   also provided for convenience in converting between @Time@ and --   other numeric types.-newtype Time = Time { unTime :: Rational }-  deriving ( Eq, Ord, Show, Read, Enum, Num, Fractional, Real, RealFrac-           , AdditiveGroup-           )--instance Newtype Time Rational where-  pack   = Time-  unpack = unTime--instance VectorSpace Time where-  type Scalar Time = Rational-  s *^ (Time t) = Time (s * t)+newtype Time n = Time { unTime :: n }+  deriving (Eq, Ord, Show, Read, Enum, Num, Fractional, Real, RealFrac, Functor) -instance InnerSpace Time where-  (Time a) <.> (Time b) = a * b+makeWrapped ''Time --- | Convert any value of a 'Real' type (including @Int@, @Integer@,---   @Rational@, @Float@, and @Double@) to a 'Time'.-toTime :: Real a => a -> Time-toTime = fromRational . toRational+instance Affine Time where+  type Diff Time = Duration+  (Time t1) .-. (Time t2) = Duration (t1 - t2)+  (Time t) .+^ (Duration d) = Time (t + d) --- | Convert a 'Time' to a value of any 'Fractional' type (such as---   @Rational@, @Float@, or @Double@).-fromTime :: Fractional a => Time -> a-fromTime = fromRational . unTime+-- instance Deadline Time a where+--   -- choose tm deadline (if before / at deadline) (if after deadline)+--   choose t1 t2 a b = if t1 <= t2 then a else b  -- | An abstract type representing /elapsed time/ between two points --   in time.  Note that durations can be negative. Literal numeric@@ -188,32 +188,24 @@ --   'Fractional' instances. 'toDuration' and 'fromDuration' are also --   provided for convenience in converting between @Duration@s and --   other numeric types.-newtype Duration = Duration { unDuration :: Rational }-  deriving ( Eq, Ord, Show, Read, Enum, Num, Fractional, Real, RealFrac-           , AdditiveGroup)+newtype Duration n = Duration n+  deriving (Eq, Ord, Show, Read, Enum, Num, Fractional, Real, RealFrac, Functor) -instance Newtype Duration Rational where-  pack   = Duration-  unpack = unDuration+makeWrapped ''Duration -instance VectorSpace Duration where-  type Scalar Duration = Rational-  s *^ (Duration d) = Duration (s * d)+instance Applicative Duration where+  pure = Duration+  Duration f <*> Duration x = Duration (f x) -instance AffineSpace Time where-  type Diff Time = Duration-  (Time t1) .-. (Time t2) = Duration (t1 - t2)-  (Time t) .+^ (Duration d) = Time (t + d)+instance Additive Duration where+  zero = 0 --- | Convert any value of a 'Real' type (including @Int@, @Integer@,---   @Rational@, @Float@, and @Double@) to a 'Duration'.-toDuration :: Real a => a -> Duration-toDuration = fromRational . toRational+instance Num n => Semigroup (Duration n) where+  (<>) = (^+^) --- | Convert a 'Duration' to any other 'Fractional' type (such as---   @Rational@, @Float@, or @Double@).-fromDuration :: Fractional a => Duration -> a-fromDuration = fromRational . unDuration+instance Num n => Monoid (Duration n) where+  mappend = (<>)+  mempty  = 0  -- | An @Era@ is a concrete span of time, that is, a pair of times --   representing the start and end of the era. @Era@s form a@@ -224,23 +216,24 @@ -- --   @Era@ is abstract. To construct @Era@ values, use 'mkEra'; to --   deconstruct, use 'start' and 'end'.-newtype Era = Era (Min Time, Max Time)-  deriving (Semigroup, Show)+newtype Era n = Era (Min (Time n), Max (Time n))+  deriving (Show, Semigroup) + -- | Create an 'Era' by specifying start and end 'Time's.-mkEra :: Time -> Time -> Era+mkEra :: Time n -> Time n -> Era n mkEra s e = Era (Min s, Max e)  -- | Get the start 'Time' of an 'Era'.-start :: Era -> Time+start :: Era n -> Time n start (Era (Min t, _)) = t  -- | Get the end 'Time' of an 'Era'.-end :: Era -> Time+end :: Era n -> Time n end (Era (_, Max t)) = t  -- | Compute the 'Duration' of an 'Era'.-duration :: Era -> Duration+duration :: Num n => Era n -> Duration n duration = (.-.) <$> end <*> start  ------------------------------------------------------------@@ -252,10 +245,11 @@ --   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        :: Era-                         , runDynamic :: Time -> a++data Dynamic a = Dynamic { era        :: Era Rational+                         , runDynamic :: Time Rational -> a                          }-  deriving (Functor)+  deriving Functor  -- | 'Dynamic' is an instance of 'Apply' (/i.e./ 'Applicative' without --   'pure'): a time-varying function is applied to a time-varying@@ -265,6 +259,7 @@ --   'pure': the era would have to be empty, but there is no such --   thing as an empty era (that is, 'Era' is not an instance of --   'Monoid').+ instance Apply Dynamic where   (Dynamic d1 f1) <.> (Dynamic d2 f2) = Dynamic (d1 <> d2) (f1 <.> f2) @@ -277,15 +272,15 @@  -- | Create a 'Dynamic' from a start time, an end time, and a --   time-varying value.-mkDynamic :: Time -> Time -> (Time -> a) -> Dynamic a+mkDynamic :: Time Rational -> Time Rational -> (Time Rational -> a) -> Dynamic a mkDynamic s e = Dynamic (mkEra s e)  -- | Fold for 'Dynamic'.-onDynamic :: (Time -> Time -> (Time -> a) -> b) -> Dynamic a -> b+onDynamic :: (Time Rational -> Time Rational -> (Time Rational -> a) -> b) -> Dynamic a -> b onDynamic f (Dynamic e d) = f (start e) (end e) d  -- | Shift a 'Dynamic' value by a certain duration.-shiftDynamic :: Duration -> Dynamic a -> Dynamic a+shiftDynamic :: Duration Rational -> Dynamic a -> Dynamic a shiftDynamic sh =   onDynamic $ \s e d ->     mkDynamic@@ -321,37 +316,29 @@ newtype Active a = Active (MaybeApply Dynamic a)   deriving (Functor, Apply, Applicative) -instance Newtype (Active a) (MaybeApply Dynamic a) where-  pack              = Active-  unpack (Active m) = m--instance Newtype (MaybeApply f a) (Either (f a) a) where-  pack   = MaybeApply-  unpack = runMaybeApply+makeWrapped ''Active+makeWrapped ''MaybeApply --- | Ideally this would be defined in the @newtype@ package.  If it is---   ever added we can remove it from here.-over2 :: (Newtype n o, Newtype n' o', Newtype n'' o'')-      => (o -> n) -> (o -> o' -> o'') -> (n -> n' -> n'')-over2 _ f n1 n2 = pack (f (unpack n1) (unpack n2))+active :: Iso' (Active a) (Either (Dynamic a) a)+active = _Wrapped . _Wrapped  -- | Active values over a type with a 'Semigroup' instance are also an --   instance of 'Semigroup'.  Two active values are combined --   pointwise; the resulting value is constant iff both inputs are. instance Semigroup a => Semigroup (Active a) where-  (<>) = (over2 Active . over2 MaybeApply) combine+  (view active -> a) <> (view active -> b) = review active $ combine a b    where-    combine (Right m1) (Right m2)-      = Right (m1 <> m2)+     combine (Right m1) (Right m2)+       = Right (m1 <> m2) -    combine (Left (Dynamic dur f)) (Right m)-      = Left (Dynamic dur (f <> const m))+     combine (Left (Dynamic dur f)) (Right m)+       = Left (Dynamic dur (f <> const m)) -    combine (Right m) (Left (Dynamic dur f))-      = Left (Dynamic dur (const m <> f))+     combine (Right m) (Left (Dynamic dur f))+       = Left (Dynamic dur (const m <> f)) -    combine (Left d1) (Left d2)-      = Left (d1 <> d2)+     combine (Left d1) (Left d2)+       = Left (d1 <> d2)  instance (Monoid a, Semigroup a) => Monoid (Active a) where   mempty  = Active (MaybeApply (Right mempty))@@ -363,7 +350,7 @@  -- | Create a dynamic 'Active' from a start time, an end time, and a --   time-varying value.-mkActive :: Time -> Time -> (Time -> a) -> Active a+mkActive :: Time Rational -> Time Rational -> (Time Rational -> a) -> Active a mkActive s e f = fromDynamic (mkDynamic s e f)  -- | Fold for 'Active's.  Process an 'Active a', given a function to@@ -375,11 +362,14 @@  -- | 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+modActive+  :: (a -> b)+  -> (Dynamic a -> Dynamic b)+  -> Active a -> Active b modActive f g = onActive (pure . f) (fromDynamic . g)  -- | Interpret an 'Active' value as a function from time.-runActive :: Active a -> (Time -> a)+runActive :: Active a -> Time Rational -> a runActive = onActive const runDynamic  -- | Get the value of an @Active a@ at the beginning of its era.@@ -392,7 +382,7 @@  -- | Get the 'Era' of an 'Active' value (or 'Nothing' if it is --   a constant/pure value).-activeEra :: Active a -> Maybe Era+activeEra :: Active a -> Maybe (Era Rational) activeEra = onActive (const Nothing) (Just . era)  -- | Test whether an 'Active' value is constant.@@ -431,7 +421,7 @@  -- | @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 -> Time -> Active a+interval :: Fractional a => Time Rational -> Time Rational -> Active a interval a b = mkActive a b (fromRational . unTime)  -- | @stretch s act@ \"stretches\" the active @act@ so that it takes@@ -445,7 +435,9 @@ -- | @stretchTo d@ 'stretch'es 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.-stretchTo :: Duration -> Active a -> Active a+-- [AJG: conditions (1) and (3) no longer true: to consider changing]++stretchTo :: Duration Rational -> Active a -> Active a stretchTo d a   | d <= 0                               = a   | (duration <$> activeEra a) == Just 0 = a@@ -459,7 +451,7 @@  -- | @shift d act@ shifts the start time of @act@ by duration @d@. --   Has no effect on constant values.-shift :: Duration -> Active a -> Active a+shift :: Duration Rational -> Active a -> Active a shift sh = modActive id (shiftDynamic sh)  -- | Reverse an active value so the start of its era gets mapped to@@ -471,11 +463,12 @@ backwards =   modActive id . onDynamic $ \s e d ->     mkDynamic s e-      (\t -> d (e - t + s))+      (\t -> d (s .+^ (e .-. t))) + -- | Take a \"snapshot\" of an active value at a particular time, --   resulting in a constant value.-snapshot :: Time -> Active a -> Active a+snapshot :: Time Rational -> Active a -> Active a snapshot t a = pure (runActive a t)  -- | \"Clamp\" an active value so that it is constant before and after@@ -490,6 +483,7 @@ -- --   See also 'clampBefore' and 'clampAfter', which clamp only before --   or after the era, respectively.+ clamp :: Active a -> Active a clamp =   modActive id . onDynamic $ \s e d ->@@ -508,6 +502,8 @@ clampBefore :: Active a -> Active a clampBefore = undefined +--- XXX These are undefined!+ -- | \"Clamp\" an active value so that it is constant after the end --   of its era.  For example, @clampBefore 'ui'@ can be visualized as --@@ -517,6 +513,7 @@ clampAfter :: Active a -> Active a clampAfter = undefined + -- | \"Trim\" an active value so that it is empty outside its era. --   @trim@ has no effect on constant values. --@@ -532,6 +529,7 @@ -- --   See also 'trimBefore' and 'trimActive', which trim only before or --   after the era, respectively.+ trim :: Monoid a => Active a -> Active a trim =   modActive id . onDynamic $ \s e d ->@@ -541,6 +539,7 @@                           | otherwise -> d t       ) + -- | \"Trim\" an active value so that it is empty /before/ the start --   of its era. For example, @trimBefore 'ui'@ can be visualized as --@@ -572,7 +571,7 @@ -- | 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 -> Active a -> Active a+setEra :: Era Rational -> Active a -> Active a setEra er =   onActive     (mkActive (start er) (end er) . const)@@ -581,7 +580,7 @@ -- | @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 -> Active a -> Active a+atTime :: Time Rational -> Active a -> Active a atTime t a = maybe a (\e -> shift (t .-. start e) a) (activeEra a)  -- | @a1 \`after\` a2@ produces an active that behaves like @a1@ but is@@ -611,7 +610,7 @@ --   return the first. (|>>) :: Active a -> Active a -> Active a a1 |>> a2 = (fromJust . getFirst) <$>-             (trimAfter (First . Just <$> a1) ->> trimBefore (First . Just <$> a2))+            (trimAfter (First . Just <$> a1) ->> trimBefore (First . Just <$> a2))  -- XXX implement 'movie' with a balanced fold @@ -634,12 +633,12 @@ --   It is an error to call @discrete@ on the empty list. discrete :: [a] -> Active a discrete [] = error "Data.Active.discrete must be called with a non-empty list."-discrete xs = f <$> (ui :: Active Rational)-  where f t | t <= 0    = arr ! 0-            | t >= 1    = arr ! (n-1)-            | otherwise = arr ! floor (t * fromIntegral n)-        n   = length xs-        arr = listArray (0, n-1) xs+discrete xs = f <$> ui+  where f (t :: Rational)+            | t <= 0    = V.unsafeHead v+            | t >= 1    = V.unsafeLast v+            | otherwise = V.unsafeIndex v $ floor (t * fromIntegral (V.length v))+        v = V.fromList xs  -- | @simulate r act@ simulates the 'Active' value @act@, returning a --   list of \"snapshots\" taken at regular intervals from the start@@ -651,6 +650,7 @@ --   times), a list of length 1 is returned, containing the constant --   value. simulate :: Rational -> Active a -> [a]+simulate 0    = const [] simulate rate =   onActive (:[])            (\d -> map (runDynamic d)@@ -659,3 +659,4 @@                        in  [s, s + 1^/rate .. e]                       )            )+
test/active-tests.hs view
@@ -1,26 +1,32 @@+{-# LANGUAGE CPP              #-}+{-# LANGUAGE FlexibleContexts #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module Main where -import Control.Applicative-import Control.Monad   (when)-import Data.Semigroup+#if __GLASGOW_HASKELL__ < 710+import           Control.Applicative+#endif -import System.Exit     (exitFailure)+import           Control.Monad       (unless)+import           Data.Semigroup -import Test.QuickCheck-import Text.Printf     (printf)+import           System.Exit         (exitFailure) -import Data.Active-import Data.VectorSpace-import Data.AffineSpace+import           Test.QuickCheck+import           Text.Printf         (printf) +import           Data.Active++import           Linear.Affine+import           Linear.Vector+ main :: IO () main = do-    results <- mapM (\(s,t) -> printf "%-40s" s >> t) tests-    when (not . all isSuccess $ results) $ exitFailure+  results <- mapM (\(s,t) -> printf "%-40s" s >> t) tests+  unless (all isSuccess results) exitFailure   where     isSuccess (Success{}) = True-    isSuccess _ = False+    isSuccess _           = False     qc x = quickCheckWithResult (stdArgs { maxSuccess = 200 }) x     tests = [ ("era/start",                   qc prop_era_start          )             , ("era/end",                     qc prop_era_end            )@@ -42,17 +48,19 @@             , ("atTime/start",                qc prop_atTime_start       )             , ("atTime/fun",                  qc prop_atTime_fun         )             ]+{-# ANN main ("HLint: ignore Eta reduce" :: String) #-}+-- eta reducing qc breaks it  instance Arbitrary Any where   arbitrary = Any <$> arbitrary -instance Arbitrary Time where+instance (Arbitrary n, Fractional n, Real n) => Arbitrary (Time n) where   arbitrary = fromRational <$> arbitrary -instance CoArbitrary Time where+instance (CoArbitrary n, Real n) => CoArbitrary (Time n) where   coarbitrary t = coarbitrary (toRational t) -instance Arbitrary Duration where+instance (Arbitrary n, Fractional n, Real n) => Arbitrary (Duration n) where   arbitrary = (fromRational . abs) <$> arbitrary  instance Arbitrary a => Arbitrary (Dynamic a) where@@ -71,35 +79,35 @@  instance Show a => Show (Active a) where   show = onActive (\c -> "<<" ++ show c ++ ">>")-                  (\d -> show d)+                  show -prop_era_start :: Time -> Time -> Bool+prop_era_start :: Time Rational -> Time Rational -> Bool prop_era_start t1 t2 = start (mkEra t1 t2) == t1 -prop_era_end :: Time -> Time -> Bool+prop_era_end :: Time Rational -> Time Rational -> Bool prop_era_end t1 t2 = end (mkEra t1 t2) == t2 -prop_duration :: Time -> Time -> Bool+prop_duration :: Time Rational -> Time Rational -> Bool prop_duration t1 t2 = duration (mkEra t1 t2) == (t2 .-. t1) -prop_shiftDynamic_start :: Duration -> Dynamic Bool -> Bool+prop_shiftDynamic_start :: Duration Rational -> Dynamic Bool -> Bool prop_shiftDynamic_start dur dyn   = (start . era) (shiftDynamic dur dyn) == ((start . era) dyn .+^ dur) -prop_shiftDynamic_end :: Duration -> Dynamic Bool -> Bool+prop_shiftDynamic_end :: Duration Rational -> Dynamic Bool -> Bool prop_shiftDynamic_end dur dyn   = (end . era) (shiftDynamic dur dyn) == ((end . era) dyn .+^ dur) -prop_shiftDynamic_fun :: Duration -> Dynamic Bool -> Time -> Bool+prop_shiftDynamic_fun :: Duration Rational -> Dynamic Bool -> Time Rational -> Bool prop_shiftDynamic_fun dur dyn t   = runDynamic dyn t == runDynamic (shiftDynamic dur dyn) (t .+^ dur) -prop_active_semi_hom :: Active Any -> Active Any -> Time -> Bool+prop_active_semi_hom :: Active Any -> Active Any -> Time Rational -> Bool prop_active_semi_hom a1 a2 t =   runActive a1 t <> runActive a2 t == runActive (a1 <> a2) t -prop_ui_id :: Time -> Bool-prop_ui_id t = runActive (ui :: Active Time) t == t+prop_ui_id :: Time Rational -> Bool+prop_ui_id t = runActive (ui :: Active (Time Rational)) t == t  prop_stretch_start :: Rational -> Active Bool -> Bool prop_stretch_start r a@@ -115,7 +123,7 @@   = runActive a t    runActive (stretch r t) -} -prop_stretchTo_dur :: Positive Duration -> Active Bool -> Property+prop_stretchTo_dur :: Positive (Duration Rational) -> Active Bool -> Property prop_stretchTo_dur (Positive dur) a   = isDynamic a && ((duration <$> activeEra a) /= Just 0)     ==> (duration <$> activeEra (stretchTo dur a)) == Just dur@@ -136,20 +144,20 @@  where a1 = fromDynamic d1        a2 = fromDynamic d2 -prop_shift_start :: Duration -> Active Bool -> Bool+prop_shift_start :: Duration Rational -> Active Bool -> Bool prop_shift_start d a =   ((.+^ d) . start <$> activeEra a) == (start <$> activeEra (shift d a)) -prop_shift_end :: Duration -> Active Bool -> Bool+prop_shift_end :: Duration Rational -> Active Bool -> Bool prop_shift_end d a =   ((.+^ d) . end <$> activeEra a) == (end <$> activeEra (shift d a)) -prop_atTime_start :: Time -> Dynamic Bool -> Bool+prop_atTime_start :: Time Rational -> Dynamic Bool -> Bool prop_atTime_start t dyn =     (start <$> activeEra (atTime t a)) == Just t   where a = fromDynamic dyn -prop_atTime_fun :: Time -> Dynamic Bool -> Duration -> Bool+prop_atTime_fun :: Time Rational -> Dynamic Bool -> Duration Rational -> Bool prop_atTime_fun t dyn d =     runActive (atTime t a) (t .+^ d) == runActive a (s .+^ d)   where a = fromDynamic dyn