packages feed

varying 0.7.1.1 → 0.8.0.0

raw patch · 7 files changed

+315/−220 lines, 7 filesdep +doctestdep ~basedep ~transformersPVP ok

version bump matches the API change (PVP)

Dependencies added: doctest

Dependency ranges changed: base, transformers

API changes (from Hackage documentation)

- Control.Varying.Tween: type TweenT f t m = SplineT f t (StateT f m)
+ Control.Varying.Tween: data TweenT f t m a
+ Control.Varying.Tween: instance Control.Monad.Trans.Class.MonadTrans (Control.Varying.Tween.TweenT f t)
+ Control.Varying.Tween: instance GHC.Base.Monad m => GHC.Base.Applicative (Control.Varying.Tween.TweenT f t m)
+ Control.Varying.Tween: instance GHC.Base.Monad m => GHC.Base.Functor (Control.Varying.Tween.TweenT f t m)
+ Control.Varying.Tween: instance GHC.Base.Monad m => GHC.Base.Monad (Control.Varying.Tween.TweenT f t m)
+ Control.Varying.Tween: instance GHC.Generics.Generic (Control.Varying.Tween.TweenT f t m a)
- Control.Varying.Spline: capture :: Monad m => SplineT a b m c -> SplineT a b m (Event b, c)
+ Control.Varying.Spline: capture :: Monad m => SplineT a b m c -> SplineT a b m (Maybe b, c)
- Control.Varying.Tween: runTweenT :: TweenT f t m x -> f -> f -> m (Either x (t, TweenT f t m x), f)
+ Control.Varying.Tween: runTweenT :: Functor m => TweenT f t m a -> f -> f -> m (Either a (t, TweenT f t m a), f)
- Control.Varying.Tween: tweenStream :: (Monad m, Num f) => TweenT f t m x -> t -> VarT m f t
+ Control.Varying.Tween: tweenStream :: forall m f t x. (Functor m, Monad m, Num f) => TweenT f t m x -> t -> VarT m f t
- Control.Varying.Tween: type Tween f t = TweenT f t Identity
+ Control.Varying.Tween: type Tween f t a = TweenT f t Identity a

Files

changelog.md view
@@ -27,6 +27,10 @@  0.7.0.0 - added proofs, reduced API size by removing trivial or weird (special)           combinators, changed some names, Event is a synonym of Maybe, removed-	  Time (moved functions to Event), renamed Event.mergeE to Event.bothE,-          added Spline.untilProc and Spline.whileProc, documentation - working -	  towards 1.0+      Time (moved functions to Event), renamed Event.mergeE to Event.bothE,+          added Spline.untilProc and Spline.whileProc, documentation - working+      towards 1.0++0.7.1.2 - Fixed broken ArrowLoop instance, updated documentation.++0.8.0.0 - TweenT is a newtype.
src/Control/Varying.hs view
@@ -27,3 +27,6 @@ import           Control.Varying.Event  as V import           Control.Varying.Spline as V import           Control.Varying.Tween  as V++-- TODO: CICD and auto-push master to hackage.+-- This would be very nice.
src/Control/Varying/Core.hs view
@@ -92,6 +92,7 @@     where g (b, vb) = (f b, f <$> vb)  -- | A var is a category.+-- -- @ --   id = var id --   f . g = g >>> f@@ -180,6 +181,7 @@ -- | Inputs can depend on outputs as long as no time-travel is required. -- -- This isn't the best example but it does make a good test case:+-- -- >>> :{ -- let --   testVar :: VarT IO Double (Maybe Double)
src/Control/Varying/Spline.hs view
@@ -15,7 +15,6 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs            #-} {-# LANGUAGE LambdaCase       #-}-{-# LANGUAGE TupleSections    #-} module Control.Varying.Spline   ( -- * Spline     Spline@@ -51,10 +50,7 @@ import           Control.Varying.Core import           Control.Varying.Event import           Data.Functor.Identity-import           Data.Monoid --- $setup--- >>> import Control.Varying.Time  -- | 'SplineT' shares all the types of 'VarT' and adds a result value. Its -- monad, input and output types (@m@, @a@ and @b@, respectively) represent the@@ -101,6 +97,7 @@                        Left  c               -> runSplineT (f c) a                        Right (b, SplineT s1) -> return $ Right (b, SplineT $ g s1) + -- | A spline responds to 'pure' by returning a spline that never produces an -- output value and immediately returns the argument. It responds to '<*>' by -- applying the left arguments result value (the function) to the right@@ -117,9 +114,9 @@   pure = return   sf <*> sx = do     f <- sf-    x <- sx-    return $ f x+    f <$> sx + -- | A spline is a transformer by running the effect and immediately concluding, -- using the effect's result as the result value. --@@ -315,21 +312,39 @@ -- spline's result. This is helpful when you want to sample the last -- output value in order to determine the next spline to sequence. --+-- The tupled value is returned in as a 'Maybe b' since it is not+-- guaranteed that an output value is produced before a Spline concludes.+-- -- >>> :{--- let s = do (Just x, "boom") <- capture $ do step 0---                                             step 1---                                             step 2---                                             return "boom"---            -- x is 2---            step $ x + 1--- in testVarOver (outputStream s 666) [(),(),(),()]+-- let+--   s :: MonadIO m => SplineT () Int m String+--   s = do+--     (mayX, boomStr) <-+--       capture+--         $ do+--           step 0+--           step 1+--           step 2+--           return "boom"+--     -- x is 2, but 'capture' can't be sure of that+--     maybe+--       (return "Failure")+--       ( (>> return boomStr)+--         . step+--         . (+1)+--       )+--       mayX+-- in+--   testVarOver (outputStream s 666) [(),(),(),()] -- >>> :} -- 0 -- 1 -- 2 -- 3-capture :: Monad m-        => SplineT a b m c -> SplineT a b m (Event b, c)+capture+  :: Monad m+  => SplineT a b m c+  -> SplineT a b m (Maybe b, c) capture = SplineT . f Nothing     where f mb s = runSplineT s >=> return . \case             Left c        -> Left (mb, c)
src/Control/Varying/Tween.hs view
@@ -13,17 +13,15 @@ --   time you use. At some point it would be great to be able to tween --   arbitrary types, and possibly tween one type into another (pipe --   dreams).--{-# LANGUAGE Rank2Types   #-}+{-# LANGUAGE DeriveGeneric              #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE Rank2Types                 #-}+{-# LANGUAGE ScopedTypeVariables        #-} module Control.Varying.Tween   ( -- * Tweening types     Easing   , TweenT   , Tween-    -- * Running tweens-  , runTweenT-  , scanTween-  , tweenStream     -- * Creating tweens     -- $creation   , tween@@ -31,6 +29,8 @@   , constant   , withTween   , withTween_+    -- * Combining tweens+    -- $combining     -- * Interpolation functions     -- $lerping   , linear@@ -47,26 +47,50 @@   , easeOutCubic   , easeInQuad   , easeOutQuad-    -- * Writing your own tweens-    -- $writing+    -- * Running tweens+  , tweenStream+  , runTweenT+  , scanTween   ) where  import           Control.Monad             (void) import           Control.Monad.Trans.State (StateT, evalStateT, get, put,                                             runStateT)+import           Control.Monad.Trans.Class (MonadTrans (..)) import           Control.Varying.Core      (VarT (..), done)+import           Control.Varying.Event     (after) import           Control.Varying.Spline    (SplineT (..), mapOutput, scanSpline,                                             untilEvent_)-import           Control.Varying.Event     (after)+import           Data.Bifunctor            (first, second) import           Data.Functor.Identity     (Identity)+import           GHC.Generics              (Generic) ++-- $setup+-- >>> import Control.Varying.Core++ --------------------------------------------------------------------------------+-- | An easing function. The parameters are often named `c`, `t` and `b`,+-- where `c` is the total change in value over the complete duration+-- (endValue - startValue), `t` is the current percentage (0 to 1) of the+-- duration that has elapsed and `b` is the start value.+--+-- To make things simple only numerical values can be tweened and the type+-- of time deltas must match the tween's value type. This may change in the+-- future :)+type Easing t f = t -> f -> t -> t+++-------------------------------------------------------------------------------- -- $lerping -- These pure functions take a `c` (total change in value, ie end - start), -- `t` (percent of duration completion) and `b` (start value) and result in -- an interpolation of a value. To see what these look like please check -- out http://www.gizma.com/easing/. --------------------------------------------------------------------------------++ -- | Ease in quadratic. easeInQuad :: (Fractional t, Real f) => Easing t f easeInQuad c t b =  c * realToFrac (t*t) + b@@ -131,30 +155,121 @@ linear :: (Floating t, Real f) => Easing t f linear c t b = c * realToFrac t + b --- TODO: Don't use StateT for leftover time in Tweens.--- This creates a funky state where running two tween splines together--- causes leftover time interplay. Think about continuations or something.+-- | A 'TweenT' is a 'SplineT' that holds a duration in local state. This allows+-- 'TweenT's to be sequenced monadically.+--+-- * 'f' is the input time delta type (the input type)+-- * 't' is the start and end value type (the output type)+-- * 'a' is the result value type+--+-- You can sequence 'TweenT's with monadic notation to produce more complex ones.+-- This is especially useful for animation:+--+-- >>> :{+-- let+--   tweenInOutExpo+--     :: ( Monad m, Floating t, Real t, Real f, Fractional f )+--     => t+--     -> t+--     -> f+--     -> TweenT f t m t+--   tweenInOutExpo start end dur = do+--       x <- tween easeInExpo start (end/2) (dur/2)+--       tween easeOutExpo x end $ dur/2+-- >>> :}+newtype TweenT f t m a+  = TweenT { unTweenT :: SplineT f t (StateT f m) a }+  deriving (Generic, Functor, Applicative, Monad) -type TweenT f t m = SplineT f t (StateT f m)-type Tween f t = TweenT f t Identity -runTweenT :: TweenT f t m x -> f -> f -> m (Either x (t, TweenT f t m x), f)-runTweenT s dt = runStateT (runSplineT s dt)+instance MonadTrans (TweenT f t) where+  lift = TweenT . lift . lift -scanTween :: (Monad m, Num f)-          => TweenT f t m a -> t -> [f] -> m [t]-scanTween s t dts = evalStateT (scanSpline s t dts) 0 +type Tween f t a = TweenT f t Identity a+++runTweenT+  :: Functor m+  => TweenT f t m a+  -> f+  -- ^ The input time delta this frame+  -> f+  -- ^ The leftover time delta from last frame+  -> m (Either a (t, TweenT f t m a), f)+  -- ^ Returns+  -- @+  -- a tuple of+  --   either+  --     the result+  --     or a tuple of+  --       this step's output value+  --       and the tween for the next step+  --   and the leftover time delta for the next step+  -- @+runTweenT (TweenT s) dt leftover =+  first (second $ second TweenT)+  <$> runStateT+        (runSplineT s dt)+        leftover+++scanTween+  :: (Monad m, Num f)+  => TweenT f t m a+  -> t+  -> [f]+  -> m [t]+scanTween (TweenT s) t dts =+  evalStateT+    (scanSpline s t dts)+    0++ -- | Converts a tween into a continuous value stream. This is the tween version--- of `outputStream`.-tweenStream :: (Monad m, Num f)-            => TweenT f t m x -> t -> VarT m f t-tweenStream s0 t0 = VarT $ f s0 t0 0-  where f s t l i = do (e, l1) <- runTweenT s i l-                       case e of-                         Left _        -> return (t, done t)-                         Right (b, s1) -> return (b, VarT $ f s1 b l1)+-- of 'Control.Varying.Spline.outputStream'. This is the preferred way to run+-- your tweens.+--+-- >>> :{+-- let+--   x :: TweenT Float Float IO Float+--   x = tween linear 0 1 1+--   y :: TweenT Float Float IO Float+--   y = tween linear 0 1 2+--   v :: VarT IO Float (Float, Float)+--   v = (,)+--       <$> tweenStream x 0+--       <*> tweenStream y 0+-- in+--   testVarOver v [0.5, 0.5, 0.5, 0.5]+-- >>> :}+-- (0.5,0.25)+-- (1.0,0.5)+-- (1.0,0.75)+-- (1.0,1.0)+tweenStream+  :: forall m f t x+   . (Functor m, Monad m, Num f)+  => TweenT f t m x+  -- ^ The tween to convert into a stream+  -> t+  -- ^ An initial output value+  -> VarT m f t+tweenStream s0 t0 = VarT $ go s0 t0 0+  where+    go ::+         TweenT f t m x -- The Tween+      -> t -- the last output value+      -> f -- the leftover time delta from last fram+      -> f -- the input time delta+      -> m (t, VarT m f t)+    go s t l i = do+      (e, l1) <- runTweenT s i l+      case e of+        Left _        -> return (t, done t)+        Right (b, s1) -> return (b, VarT $ go s1 b l1) + -------------------------------------------------------------------------------- -- $creation -- The most direct route toward tweening values is to use 'tween'@@ -174,21 +289,26 @@ -- `tween` concludes returning the latest output value. tween :: (Monad m, Real t, Real f, Fractional f)       => Easing t f -> t -> t -> f -> TweenT f t m t-tween f start end dur = SplineT g-  where c = end - start-        b = start-        g dt = do-          leftover <- get-          let t = dt + leftover+tween f start end dur =+  TweenT+    $ SplineT g+  where+    c = end - start+    b = start+    g dt = do+      leftover <- get+      let+        t = dt + leftover+      if t == dur+        then+          put 0 >> return (Right (end, return end))+        else+          if t > dur+          then+            put (t - dur - dt) >> return (Left end)+          else+            put t >> return (Right (f c (t/dur) b, SplineT g)) -          if t == dur-            then do put 0-                    return $ Right (end, return end)-            else if t > dur-              then do put $ t - dur - dt-                      return $ Left end-              else do put t-                      return $ Right (f c (t/dur) b, SplineT g)  -- | A version of 'tween' that discards the result. It is simply --@@ -202,14 +322,19 @@  -- | A version of 'tween' that maps its output using the given constant -- function.+-- -- @ -- withTween ease from to dur f = mapOutput (pure f) $ tween ease from to dur -- @ withTween :: (Monad m, Real t, Real a, Fractional a)           => Easing t a -> t -> t -> a -> (t -> x) -> TweenT a x m t-withTween ease from to dur f = mapOutput (pure f) $ tween ease from to dur+withTween ease from to dur f =+  TweenT+    $ mapOutput (pure f)+    $ unTweenT+    $ tween ease from to dur --- | A version of 'withTween' that discards its output.+-- | A version of 'withTween' that discards its result. withTween_ :: (Monad m, Real t, Real a, Fractional a)            => Easing t a -> t -> t -> a -> (t -> x) -> TweenT a x m () withTween_ ease from to dur f = Control.Monad.void (withTween ease from to dur f)@@ -217,24 +342,6 @@ -- | Creates a tween that performs no interpolation over the duration. constant :: (Monad m, Num t, Ord t)          => a -> t -> TweenT t a m a-constant value duration = pure value `untilEvent_` after duration------------------------------------------------------------------------------------ $writing--- To create your own tweens just write a function that takes a start--- value, end value and a duration and return an event stream.------ @--- tweenInOutExpo start end dur = do---     (dt, x) <- tween easeInExpo start end (dur/2)---     tween easeOutExpo x end $ dt + dur/2--- @------------------------------------------------------------------------------------ | An easing function. The parameters are often named `c`, `t` and `b`,--- where `c` is the total change in value over the complete duration--- (endValue - startValue), `t` is the current percentage (0 to 1) of the--- duration that has elapsed and `b` is the start value.------ To make things simple only numerical values can be tweened and the type--- of time deltas must match the tween's value type. This may change in the--- future :)-type Easing t f = t -> f -> t -> t+constant value duration =+  TweenT+    $ pure value `untilEvent_` after duration
+ test/DocTests.hs view
@@ -0,0 +1,7 @@+module Main where++import Test.DocTest++main :: IO ()+main =+  doctest ["src", "app"]
varying.cabal view
@@ -1,150 +1,107 @@--- Initial varying.cabal generated by cabal init.  For further--- documentation, see http://haskell.org/cabal/users-guide/---- The name of the package.-name:                varying---- The package version.  See the Haskell package versioning policy (PVP)--- for standards guiding when and how versions should be incremented.--- http://www.haskell.org/haskellwiki/Package_versioning_policy--- PVP summary:      +-+------- breaking API changes---                   | | +----- non-breaking API additions---                   | | | +--- code changes with no API change-version:             0.7.1.1---- A short (one-line) description of the package.-synopsis:            FRP through value streams and monadic splines.---- A longer description of the package.-description:         Varying is a FRP library aimed at providing a-                     simple way to describe values that change over a domain.-                     It allows monadic, applicative and arrow notation and has-                     convenience functions for tweening.---- URL for the project homepage or repository.-homepage:            https://github.com/schell/varying---- The license under which the package is released.-license:             MIT---- The file containing the license text.-license-file:        LICENSE---- The package author(s).-author:              Schell Scivally---- An email address to which users can send suggestions, bug reports, and--- patches.-maintainer:          schell@takt.com---- A copyright notice.--- copyright:--category:            Control, FRP--build-type:          Simple---- Extra files to be distributed with the package, such as examples or a--- README.--- extra-source-files:+cabal-version: 1.12 --- Constraint on the version of Cabal needed to build this package.-cabal-version:       >=1.10+-- This file has been generated from package.yaml by hpack version 0.31.2.+--+-- see: https://github.com/sol/hpack+--+-- hash: 23f79975d60664192d4aec0699c6a80542dc85db8ebfb018fd84bea51c196f7b -extra-source-files:  README.md, changelog.md+name:           varying+version:        0.8.0.0+synopsis:       FRP through value streams and monadic splines.+description:    Varying is a FRP library aimed at providing a simple way to describe values that change over a domain. It allows monadic, applicative and arrow notation and has convenience functions for tweening. Great for animation.+category:       Control, FRP+homepage:       https://github.com/schell/varying+bug-reports:    https://github.com/schell/varying/issues+author:         Schell Scivally+maintainer:     schell@takt.com+license:        MIT+license-file:   LICENSE+build-type:     Simple+extra-source-files:+    README.md+    changelog.md  source-repository head-  type:     git-  location: https://github.com/schell/varying.git+  type: git+  location: https://github.com/schell/varying  library-  ghc-options:         -Wall-  if impl(ghc >= 8)-    ghc-options:       -Wno-type-defaults--  -- Modules exported by the library.-  exposed-modules:     Control.Varying,-                       Control.Varying.Core,-                       Control.Varying.Event,-                       Control.Varying.Tween,-                       Control.Varying.Spline--  -- Modules included in this library but not exported.-  -- other-modules:--  -- LANGUAGE extensions used by modules in this package.-  -- other-extensions:--  -- Other library packages from which modules are imported.-  build-depends:       base >=4.8 && <5.0-                     , transformers >=0.3-                     , contravariant >= 1.4--  -- Directories containing source files.-  hs-source-dirs:      src--  -- Base language which the package is written in.-  default-language:    Haskell2010+  exposed-modules:+      Control.Varying+      Control.Varying.Core+      Control.Varying.Event+      Control.Varying.Spline+      Control.Varying.Tween+  other-modules:+      Paths_varying+  hs-source-dirs:+      src+  ghc-options: -Wall+  build-depends:+      base >=4.8 && <5.0+    , contravariant >=1.4+    , transformers >=0.3+  default-language: Haskell2010  executable varying-example-  ghc-options:         -Wall -threaded -rtsopts -with-rtsopts=-N-  if impl(ghc >= 8)-    ghc-options:       -Wno-type-defaults--  -- Other library packages from which modules are imported.-  build-depends:       base >=4.8 && <5.0-                     , transformers >=0.3-                     , time >=1.4-                     , varying---  -- Directories containing source files.-  hs-source-dirs:      app--  main-is:             Main.hs--  -- Base language which the package is written in.-  default-language:    Haskell2010--test-suite varying-test-  type:                exitcode-stdio-1.0-  ghc-options:         -Wall -threaded -rtsopts -with-rtsopts=-N-  if impl(ghc >= 8)-    ghc-options:       -Wno-type-defaults--  -- Other library packages from which modules are imported.-  build-depends:       base >=4.8 && <5.0-                     , time >=1.4-                     , transformers-                     , varying-                     , hspec-                     , QuickCheck--  -- Directories containing source files.-  hs-source-dirs:      test+  main-is: Main.hs+  other-modules:+      Paths_varying+  hs-source-dirs:+      app+  ghc-options: -Wall -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      base >=4.8 && <5.0+    , contravariant >=1.4+    , time >=1.4+    , transformers >=0.3+    , varying+  default-language: Haskell2010 -  main-is:             Main.hs+test-suite doctests+  type: exitcode-stdio-1.0+  main-is: DocTests.hs+  hs-source-dirs:+      test+  ghc-options: -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      base >=4.8 && <5.0+    , contravariant >=1.4+    , doctest+    , transformers >=0.3+    , varying+  default-language: Haskell2010 -  -- Base language which the package is written in.-  default-language:    Haskell2010+test-suite other+  type: exitcode-stdio-1.0+  main-is: Main.hs+  hs-source-dirs:+      test+  ghc-options: -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      QuickCheck+    , base >=4.8 && <5.0+    , contravariant >=1.4+    , hspec+    , time >=1.4+    , transformers >=0.3+    , varying+  default-language: Haskell2010  benchmark varying-bench-  type:                exitcode-stdio-1.0-  ghc-options:         -Wall -threaded -rtsopts -with-rtsopts=-N-  if impl(ghc >= 8)-    ghc-options:       -Wno-type-defaults--  -- Other library packages from which modules are imported.-  build-depends:       base >=4.8-                     , time >=1.4-                     , transformers-                     , varying-                     , criterion--  -- Directories containing source files.-  hs-source-dirs:      bench--  main-is:             Main.hs--  -- Base language which the package is written in.-  default-language:    Haskell2010+  type: exitcode-stdio-1.0+  main-is: Main.hs+  other-modules:+      Paths_varying+  hs-source-dirs:+      bench+  ghc-options: -Wall -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      base >=4.8 && <5.0+    , contravariant >=1.4+    , criterion+    , time >=1.4+    , transformers+    , varying+  default-language: Haskell2010