# 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-08: | 0.8.1.0 |

Latest on Hackage: | 0.8.1.0 |

**Schell Scivally**

**[email protected]**

`varying-0.8.1.0@sha256:cdcc23b46d821bba6bc17ab1a7336f13c16f527f8f7c77efea786e51ae0c624c,2651`

#### Module documentation for 0.8.1.0

*(full list with versions)*:

# 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