Yampa 0.11.1 → 0.12
raw patch · 6 files changed
+111/−21 lines, 6 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ FRP.Yampa: data FutureSF a b
+ FRP.Yampa: evalAt :: FutureSF a b -> DTime -> a -> (b, FutureSF a b)
+ FRP.Yampa: evalAtZero :: SF a b -> a -> (b, FutureSF a b)
+ FRP.Yampa: evalFuture :: SF a b -> a -> DTime -> (b, SF a b)
+ FRP.Yampa.Simulation: data FutureSF a b
+ FRP.Yampa.Simulation: evalAt :: FutureSF a b -> DTime -> a -> (b, FutureSF a b)
+ FRP.Yampa.Simulation: evalAtZero :: SF a b -> a -> (b, FutureSF a b)
+ FRP.Yampa.Simulation: evalFuture :: SF a b -> a -> DTime -> (b, SF a b)
Files
- CHANGELOG +7/−0
- Yampa.cabal +1/−1
- src/FRP/Yampa.hs +5/−0
- src/FRP/Yampa/MergeableRecord.hs +5/−2
- src/FRP/Yampa/Simulation.hs +90/−17
- tests/AFRPTestsCommon.hs +3/−1
CHANGELOG view
@@ -1,3 +1,10 @@+2018-10-21 Ivan Perez <ivan.perez@keera.co.uk>+ * Yampa.cabal: Version bump (0.12).+ * README.md: Documents testing.+ * src/: Introduces FutureSF, needed for testing.+ * extensions/test/: Introduces testing library.+ * Thanks to @chriz-keera.+ 2018-08-11 Ivan Perez <ivan.perez@keera.co.uk> * Yampa.cabal: Version bump (0.11.1). * README.md: Documents papers.
Yampa.cabal view
@@ -1,5 +1,5 @@ name: Yampa-version: 0.11.1+version: 0.12 cabal-version: >= 1.8 license: BSD3 license-file: LICENSE
src/FRP/Yampa.hs view
@@ -426,6 +426,11 @@ deltaEncodeBy, -- :: (a -> a -> Bool) -> DTime -> [a] -- -> (a, [(DTime, Maybe a)]) + FutureSF,+ evalAtZero,+ evalAt,+ evalFuture,+ -- * Auxiliary definitions -- Reverse function composition and arrow plumbing aids ( # ), -- :: (a -> b) -> (b -> c) -> (a -> c), infixl 9
src/FRP/Yampa/MergeableRecord.hs view
@@ -49,14 +49,17 @@ -- @ ----------------------------------------------------------------------------------------- -module FRP.Yampa.MergeableRecord (+module FRP.Yampa.MergeableRecord+ {-# DEPRECATED "No longer supported." #-}+ ( MergeableRecord(..), MR, -- Abstract mrMake, (~+~), mrMerge, mrFinalize-) where+ )+ where -- | Superclass providing operations on records. Record operations can be -- merged (composed). To obtain a record from a sequence of merging operations
src/FRP/Yampa/Simulation.hs view
@@ -1,4 +1,6 @@ {-# LANGUAGE GADTs, Rank2Types, CPP #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE MultiWayIf #-} ----------------------------------------------------------------------------------------- -- | -- Module : FRP.Yampa.Simulation@@ -12,10 +14,11 @@ -- Execution/simulation of signal functions. -- -- SFs can be executed in two ways: by running them, feeding input samples one--- by one, obtained from a monadic environment (presumably, |IO|), or by+-- by one, obtained from a monadic environment (presumably, @IO@), or by -- passing an input stream and calculating an output stream. The former is -- called /reactimation/, and the latter is called /embedding/. --+-- * Running: -- Normally, to run an SF, you would use 'reactimate', providing input samples, -- and consuming the output samples in the 'IO' monad. This function takes over -- the program, implementing a "main loop". If you want more control over the@@ -23,11 +26,14 @@ -- backend that also implements some main loop), you may want to use the -- lower-level API for reactimation ('ReactHandle', 'reactInit', 'react'). --+-- * Embedding: -- You can use 'embed' for testing, to evaluate SFs in a terminal, and to embed -- an SF inside a larger system. The helper functions 'deltaEncode' and -- 'deltaEncodeBy' facilitate producing input /signals/ from plain lists of -- input samples. --+-- This module also includes debugging aids needed to execute signal functions+-- step by step, which are used by Yampa's testing facilities. ----------------------------------------------------------------------------------------- module FRP.Yampa.Simulation (@@ -56,6 +62,14 @@ deltaEncodeBy, -- :: (a -> a -> Bool) -> DTime -> [a] -- -> (a, [(DTime, Maybe a)]) + -- * Debugging / Step by step simulation++ FutureSF,+ evalAtZero,+ evalAt,+ evalFuture,++ ) where import Control.Monad (unless)@@ -279,23 +293,7 @@ | t' <= tp = advance tp tbtbs advance _ _ = undefined --- | Spaces a list of samples by a fixed time delta, avoiding--- unnecessary samples when the input has not changed since--- the last sample.-deltaEncode :: Eq a => DTime -> [a] -> (a, [(DTime, Maybe a)])-deltaEncode _ [] = usrErr "AFRP" "deltaEncode" "Empty input list."-deltaEncode dt aas@(_:_) = deltaEncodeBy (==) dt aas ---- | 'deltaEncode' parameterized by the equality test.-deltaEncodeBy :: (a -> a -> Bool) -> DTime -> [a] -> (a, [(DTime, Maybe a)])-deltaEncodeBy _ _ [] = usrErr "AFRP" "deltaEncodeBy" "Empty input list."-deltaEncodeBy eq dt (a0:as) = (a0, zip (repeat dt) (debAux a0 as))- where- debAux _ [] = []- debAux a_prev (a:as) | a `eq` a_prev = Nothing : debAux a as- | otherwise = Just a : debAux a as- -- Embedding and missing events. -- Suppose a subsystem is super sampled. Then some of the output -- samples will have to be dropped. If we are unlycky, the dropped@@ -318,6 +316,81 @@ -- But what do we do if the inner system runs more slowly than the -- outer one? Then we need to extrapolate the output from the -- inner system, and we have the same problem with events AGAIN!++-- | Spaces a list of samples by a fixed time delta, avoiding+-- unnecessary samples when the input has not changed since+-- the last sample.+deltaEncode :: Eq a => DTime -> [a] -> (a, [(DTime, Maybe a)])+deltaEncode _ [] = usrErr "AFRP" "deltaEncode" "Empty input list."+deltaEncode dt aas@(_:_) = deltaEncodeBy (==) dt aas+++-- | 'deltaEncode' parameterized by the equality test.+deltaEncodeBy :: (a -> a -> Bool) -> DTime -> [a] -> (a, [(DTime, Maybe a)])+deltaEncodeBy _ _ [] = usrErr "AFRP" "deltaEncodeBy" "Empty input list."+deltaEncodeBy eq dt (a0:as) = (a0, zip (repeat dt) (debAux a0 as))+ where+ debAux _ [] = []+ debAux a_prev (a:as) | a `eq` a_prev = Nothing : debAux a as+ | otherwise = Just a : debAux a as+++-- * Debugging / Step by step simulation++-- | A wrapper around an initialized SF (continuation), needed for testing and+-- debugging purposes.+--+newtype FutureSF a b = FutureSF { unsafeSF :: SF' a b }+++-- | Evaluate an SF, and return an output and an initialized SF.+--+-- /WARN/: Do not use this function for standard simulation. This function is+-- intended only for debugging/testing. Apart from being potentially slower+-- and consuming more memory, it also breaks the FRP abstraction by making+-- samples discrete and step based.+evalAtZero :: SF a b+ -> a -- ^ Input sample+ -> (b, FutureSF a b) -- ^ Output x Continuation+evalAtZero (SF { sfTF = tf }) a = (b, FutureSF tf' )+ where (tf', b) = tf a+++-- | Evaluate an initialized SF, and return an output and a continuation.+--+-- /WARN/: Do not use this function for standard simulation. This function is+-- intended only for debugging/testing. Apart from being potentially slower+-- and consuming more memory, it also breaks the FRP abstraction by making+-- samples discrete and step based.+evalAt :: FutureSF a b+ -> DTime -> a -- ^ Input sample+ -> (b, FutureSF a b) -- ^ Output x Continuation+evalAt (FutureSF { unsafeSF = tf }) dt a = (b, FutureSF tf')+ where (tf', b) = (sfTF' tf) dt a+++-- | Given a signal function and time delta, it moves the signal function into+-- the future, returning a new uninitialized SF and the initial output.+--+-- While the input sample refers to the present, the time delta refers to the+-- future (or to the time between the current sample and the next sample).+--+-- /WARN/: Do not use this function for standard simulation. This function is+-- intended only for debugging/testing. Apart from being potentially slower+-- and consuming more memory, it also breaks the FRP abstraction by making+-- samples discrete and step based.+--+evalFuture :: SF a b -> a -> DTime -> (b, SF a b)+evalFuture sf a dt = (b, sf' dt)+ where (b, sf') = evalStep sf a+++-- | Steps the signal function into the future one step. It returns the current+-- output, and a signal function that expects, apart from an input, a time+-- between samples.+evalStep :: SF a b -> a -> (b, DTime -> SF a b)+evalStep (SF sf) a = (b, \dt -> SF (sfTF' sf' dt))+ where (sf', b) = sf a -- Vim modeline -- vim:set tabstop=8 expandtab:
tests/AFRPTestsCommon.hs view
@@ -1,5 +1,5 @@ {-# OPTIONS_GHC -fno-warn-tabs #-}-{- $Id: AFRPTestsCommon.hs,v 1.2 2003/11/10 21:28:58 antony Exp $+{- ****************************************************************************** * A F R P * * *@@ -160,6 +160,8 @@ ------------------------------------------------------------------------------ -- Some utilities used for testing laws ------------------------------------------------------------------------------++fun_prod f g = \(x,y) -> (f x, g y) assoc :: ((a,b),c) -> (a,(b,c)) assoc ((a,b),c) = (a,(b,c))