varying
FRP through value streams and monadic splines.
https://github.com/schell/varying
LTS Haskell 22.33: | 0.8.1.0 |
Stackage Nightly 2024-09-07: | 0.8.1.0 |
Latest on Hackage: | 0.8.1.0 |
varying-0.8.1.0@sha256:cdcc23b46d821bba6bc17ab1a7336f13c16f527f8f7c77efea786e51ae0c624c,2651
Module documentation for 0.8.1.0
varying
This library provides automaton based value streams and sequencing useful for functional reactive programming (FRP) and locally stateful programming (LSP).
Getting started
module Main where
import Control.Varying
import Control.Applicative
import Control.Concurrent (forkIO, killThread)
import Data.Functor.Identity
import Data.Time.Clock
-- | A simple 2d point type.
data Point = Point { px :: Float
, py :: Float
} deriving (Show, Eq)
newtype Delta = Delta { unDelta :: Float }
-- An exponential tween back and forth from 0 to 50 over 1 seconds that
-- loops forever. This spline takes float values of delta time as input,
-- outputs the current x value at every step.
tweenx :: Monad m => TweenT Float Float m Float
tweenx = do
-- Tween from 0 to 50 over 1 second
tween_ easeOutExpo 0 50 1
-- Chain another tween back to the starting position
tween_ easeOutExpo 50 0 1
-- Loop forever
tweenx
-- An exponential tween back and forth from 0 to 50 over 1 seconds that never
-- ends.
tweeny :: Monad m => TweenT Float Float m Float
tweeny = do
tween_ easeOutExpo 50 0 1
tween_ easeOutExpo 0 50 1
tweeny
-- Our time signal counts input delta time samples.
time :: Monad m => VarT m Delta Float
time = var unDelta
-- | Our Point value that varies over time continuously in x and y.
backAndForth :: Monad m => VarT m Delta Point
backAndForth =
-- Turn our splines into continuous output streams. We must provide
-- a starting value since splines are not guaranteed to be defined at
-- their edges.
let x = tweenStream tweenx 0
y = tweenStream tweeny 0
in
-- Construct a varying Point that takes time as an input.
(Point <$> x <*> y)
-- Stream in a time signal using the 'plug left' combinator.
-- We could similarly use the 'plug right' (~>) function
-- and put the time signal before the construction above. This is needed
-- because the tween streams take time as an input.
<~ time
main :: IO ()
main = do
putStrLn "An example of value streams using the varying library."
putStrLn "Enter a newline to continue, and then a newline to quit"
_ <- getLine
t <- getCurrentTime
tId <- forkIO $ loop backAndForth t
_ <- getLine
killThread tId
loop :: Var Delta Point -> UTCTime -> IO ()
loop v t = do
t1 <- getCurrentTime
-- Here we'll run in the Identity monad using a time delta provided by
-- getCurrentTime and diffUTCTime.
let dt = realToFrac $ diffUTCTime t1 t
Identity (Point x y, vNext) = runVarT v $ Delta dt
xStr = replicate (round x) ' ' ++ "x" ++ replicate (50 - round x) ' '
yStr = replicate (round y) ' ' ++ "y" ++ replicate (50 - round y) ' '
str = zipWith f xStr yStr
f 'x' 'y' = '|'
f 'y' 'x' = '|'
f a ' ' = a
f ' ' b = b
f _ _ = ' '
putStrLn str
loop vNext t1
Publications
The concept of VarT
that this library is built on is isomorphic to Monadic Stream Functions as defined in “Functional Reactive Programming, Refactored” (mirror).
The isomorphism is
toMSF :: Functor m => VarT m a b -> MSF m a b
toMSF = MSF . (fmap . fmap . fmap $ toMSF) . runVarT
toVarT :: Functor m => MSF m a b -> VarT m a b
toVarT = VarT . (fmap . fmap . fmap $ toVarT) . unMSF
Changes
change log
0.1.5.0 - added Control.Varying.Spline
0.2.0.0 - reordered spline type variables for MonadTrans
0.3.0.0 - updated the type of mapOutput to a more friendly, usable signature bug fixes
0.3.1.0 - added stepMany, eitherE
0.4.0.0 - Var and Spline are now parameterized with Identity, removed mix, changed the behavior of race, added untilEvent variants, added tests
0.5.0.0 - changed stepMany to remove Monoid requirement, added raceMany, added anyE, more tests and SplineT obeys Applicative and Monad laws
0.5.0.1 - removed time as dependency
0.5.0.2 - separated tweening time and value, added runSplineE, builds on all GHC since 7.6
0.6.0.0 - changed the internal type of SplineT to use Either, reducing unused output values and preventing time/space leaks. Updated tween types. Added withTween(_).
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
0.7.1.2 - Fixed broken ArrowLoop instance, updated documentation.
0.8.0.0 - TweenT is a newtype.
0.8.1.0 - Remove senseless ArrowApply instance