packages feed

Yampa 0.9.3 → 0.9.5

raw patch · 4 files changed

+157/−87 lines, 4 filesnew-uploaderPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

+ CHANGELOG view
@@ -0,0 +1,13 @@+2014-04-07 Ivan Perez <ivan.perez@keera.es>++        * Yampa.cabal: version bump (0.9.5)+        * Adds CHANGELOG to cabal file++2014-04-07 Ivan Perez <ivan.perez@keera.es>++        * Yampa.cabal: new maintainer, version bump (0.9.4).+        * src/: documentation is exposed so that Haddock can process it+        * No interface changes++Copyright (c) 2003, Henrik Nilsson, Antony Courtney and Yale University.+All rights reserved.
Yampa.cabal view
@@ -1,10 +1,10 @@ name: Yampa-version: 0.9.3+version: 0.9.5 cabal-version: >= 1.6 license: BSD3 license-file: LICENSE author: Henrik Nilsson, Antony Courtney-maintainer: George Giorgidze (giorgidze@gmail.com)+maintainer: Ivan Perez (ivan.perez@keera.co.uk) homepage: http://www.haskell.org/haskellwiki/Yampa category: Reactivity, FRP synopsis: Library for programming hybrid systems.@@ -30,8 +30,10 @@   examples/Elevator/Elevator.hs,   examples/Elevator/TestElevatorMain.hs,   examples/TailgatingDetector/TailgatingDetector.hs,-  examples/TailgatingDetector/TestTGMain.hs+  examples/TailgatingDetector/TestTGMain.hs, +  CHANGELOG+ library   hs-source-dirs:  src   ghc-options : -O3 -Wall -fno-warn-name-shadowing@@ -57,4 +59,4 @@  source-repository head   type:     git-  location: git://github.com/giorgidze/Yampa.git+  location: git://github.com/ivanperez-keera/Yampa.git
src/FRP/Yampa.hs view
@@ -135,24 +135,27 @@ -- For optimization     arrPrim, arrEPrim, --- Basic signal functions+-- * Signal functions++-- ** Basic signal functions     identity,		-- :: SF a a     constant,		-- :: b -> SF a b     localTime,		-- :: SF a Time     time,               -- :: SF a Time,	Other name for localTime. --- Initialization+-- ** Initialization     (-->),		-- :: b -> SF a b -> SF a b,		infixr 0     (>--),		-- :: a -> SF a b -> SF a b,		infixr 0     (-=>),              -- :: (b -> b) -> SF a b -> SF a b      infixr 0     (>=-),              -- :: (a -> a) -> SF a b -> SF a b      infixr 0     initially,		-- :: a -> SF a a --- Simple, stateful signal processing+-- ** Simple, stateful signal processing     sscan,		-- :: (b -> a -> b) -> b -> SF a b     sscanPrim,		-- :: (c -> a -> Maybe (c, b)) -> c -> b -> SF a b --- Basic event sources+-- * Events+-- ** Basic event sources     never, 		-- :: SF a (Event b)     now,		-- :: b -> SF a (Event b)     after,		-- :: Time -> b -> SF a (Event b)@@ -167,13 +170,39 @@     edgeJust,		-- :: SF (Maybe a) (Event a)     edgeBy,		-- :: (a -> a -> Maybe b) -> a -> SF a (Event b) --- Stateful event suppression+-- ** Stateful event suppression     notYet,		-- :: SF (Event a) (Event a)     once,		-- :: SF (Event a) (Event a)     takeEvents,		-- :: Int -> SF (Event a) (Event a)     dropEvents,		-- :: Int -> SF (Event a) (Event a) --- Basic switchers+-- ** Pointwise functions on events+    noEvent,		-- :: Event a+    noEventFst,		-- :: (Event a, b) -> (Event c, b)+    noEventSnd,		-- :: (a, Event b) -> (a, Event c)+    event, 		-- :: a -> (b -> a) -> Event b -> a+    fromEvent,		-- :: Event a -> a+    isEvent,		-- :: Event a -> Bool+    isNoEvent,		-- :: Event a -> Bool+    tag, 		-- :: Event a -> b -> Event b,		infixl 8+    tagWith,            -- :: b -> Event a -> Event b,+    attach,		-- :: Event a -> b -> Event (a, b),	infixl 8+    lMerge, 		-- :: Event a -> Event a -> Event a,	infixl 6+    rMerge,		-- :: Event a -> Event a -> Event a,	infixl 6+    merge,		-- :: Event a -> Event a -> Event a,	infixl 6+    mergeBy,		-- :: (a -> a -> a) -> Event a -> Event a -> Event a+    mapMerge,           -- :: (a -> c) -> (b -> c) -> (a -> b -> c) +                        --    -> Event a -> Event b -> Event c+    mergeEvents,        -- :: [Event a] -> Event a+    catEvents,		-- :: [Event a] -> Event [a]+    joinE,		-- :: Event a -> Event b -> Event (a,b),infixl 7+    splitE,		-- :: Event (a,b) -> (Event a, Event b)+    filterE,	 	-- :: (a -> Bool) -> Event a -> Event a+    mapFilterE,		-- :: (a -> Maybe b) -> Event a -> Event b+    gate,		-- :: Event a -> Bool -> Event a,	infixl 8++-- * Switching+-- ** Basic switchers     switch,  dSwitch,	-- :: SF a (b, Event c) -> (c -> SF a b) -> SF a b     rSwitch, drSwitch,	-- :: SF a b -> SF (a,Event (SF a b)) b     kSwitch, dkSwitch,	-- :: SF a b@@ -181,7 +210,8 @@ 			--    -> (SF a b -> c -> SF a b) 			--    -> SF a b --- Parallel composition and switching over collections with broadcasting+-- ** Parallel composition and switching+-- *** Parallel composition and switching over collections with broadcasting     parB,		-- :: Functor col => col (SF a b) -> SF a (col b)     pSwitchB,dpSwitchB, -- :: Functor col => 			--        col (SF a b)@@ -193,7 +223,7 @@ 			--	  -> SF (a, Event (col (SF a b)->col (SF a b))) 			--	        (col b) --- Parallel composition and switching over collections with general routing+-- *** Parallel composition and switching over collections with general routing     par,		-- Functor col =>     			--     (forall sf . (a -> col sf -> col (b, sf)))     			--     -> col (SF b c)@@ -210,13 +240,14 @@ 			--    -> SF (a, Event (col (SF b c) -> col (SF b c))) 			--	    (col c) --- Wave-form generation+-- * Discrete to continuous-time signal functions+-- ** Wave-form generation     old_hold,		-- :: a -> SF (Event a) a     hold,		-- :: a -> SF (Event a) a     dHold,		-- :: a -> SF (Event a) a     trackAndHold,	-- :: a -> SF (Maybe a) a --- Accumulators+-- ** Accumulators     old_accum,		-- :: a -> SF (Event (a -> a)) (Event a)     old_accumBy,	-- :: (b -> a -> b) -> b -> SF (Event a) (Event b)     old_accumFilter,	-- :: (c -> a -> (c, Maybe b)) -> c@@ -229,57 +260,35 @@     accumFilter,	-- :: (c -> a -> (c, Maybe b)) -> c 			--    -> SF (Event a) (Event b) --- Delays+-- * Delays+-- ** Basic delays     old_pre, old_iPre,     pre,		-- :: SF a a     iPre,		-- :: a -> SF a a --- Timed delays+-- ** Timed delays     delay,		-- :: Time -> a -> SF a a --- Integration and differentiation-    integral,		-- :: VectorSpace a s => SF a a--    derivative,		-- :: VectorSpace a s => SF a a		-- Crude!-    imIntegral,		-- :: VectorSpace a s => a -> SF a a+-- * State keeping combinators --- Loops with guaranteed well-defined feedback+-- ** Loops with guaranteed well-defined feedback     loopPre, 		-- :: c -> SF (a,c) (b,c) -> SF a b     loopIntegral,	-- :: VectorSpace c s => SF (a,c) (b,c) -> SF a b --- Pointwise functions on events-    noEvent,		-- :: Event a-    noEventFst,		-- :: (Event a, b) -> (Event c, b)-    noEventSnd,		-- :: (a, Event b) -> (a, Event c)-    event, 		-- :: a -> (b -> a) -> Event b -> a-    fromEvent,		-- :: Event a -> a-    isEvent,		-- :: Event a -> Bool-    isNoEvent,		-- :: Event a -> Bool-    tag, 		-- :: Event a -> b -> Event b,		infixl 8-    tagWith,            -- :: b -> Event a -> Event b,-    attach,		-- :: Event a -> b -> Event (a, b),	infixl 8-    lMerge, 		-- :: Event a -> Event a -> Event a,	infixl 6-    rMerge,		-- :: Event a -> Event a -> Event a,	infixl 6-    merge,		-- :: Event a -> Event a -> Event a,	infixl 6-    mergeBy,		-- :: (a -> a -> a) -> Event a -> Event a -> Event a-    mapMerge,           -- :: (a -> c) -> (b -> c) -> (a -> b -> c) -                        --    -> Event a -> Event b -> Event c-    mergeEvents,        -- :: [Event a] -> Event a-    catEvents,		-- :: [Event a] -> Event [a]-    joinE,		-- :: Event a -> Event b -> Event (a,b),infixl 7-    splitE,		-- :: Event (a,b) -> (Event a, Event b)-    filterE,	 	-- :: (a -> Bool) -> Event a -> Event a-    mapFilterE,		-- :: (a -> Maybe b) -> Event a -> Event b-    gate,		-- :: Event a -> Bool -> Event a,	infixl 8+-- ** Integration and differentiation+    integral,		-- :: VectorSpace a s => SF a a --- Noise (random signal) sources and stochastic event sources+    derivative,		-- :: VectorSpace a s => SF a a		-- Crude!+    imIntegral,		-- :: VectorSpace a s => a -> SF a a++-- * Noise (random signal) sources and stochastic event sources     noise,		-- :: noise :: (RandomGen g, Random b) => 			--        g -> SF a b     noiseR,		-- :: noise :: (RandomGen g, Random b) => 			--        (b,b) -> g -> SF a b     occasionally,	-- :: RandomGen g => g -> Time -> b -> SF a (Event b) --- Reactimation+-- * Reactimation     reactimate,		-- :: IO a 	      		--    -> (Bool -> IO (DTime, Maybe a)) 	      		--    -> (Bool -> b -> IO Bool)@@ -295,7 +304,9 @@                         --    -> (DTime,Maybe a)                         --    -> IO Bool --- Embedding (tentative: will be revisited)+-- * Embedding++--  (tentative: will be revisited)     DTime,		-- [s] Sampling interval, always > 0.     embed,		-- :: SF a b -> (a, [(DTime, Maybe a)]) -> [b]     embedSynch,		-- :: SF a b -> (a, [(DTime, Maybe a)]) -> SF Double b@@ -340,7 +351,7 @@ -- switch would need to remember the record, since it is the only place -- where signal functions get started. So it wouldn't cost all that much. --- Time is used both for time intervals (duration), and time w.r.t. some+-- | Time is used both for time intervals (duration), and time w.r.t. some -- agreed reference point in time. Conceptually, Time = R, i.e. time can be 0 -- or even negative. type Time = Double	-- [s]@@ -349,13 +360,15 @@ -- DTime is the time type for lengths of sample intervals. Conceptually, -- DTime = R+ = { x in R | x > 0 }. Don't assume Time and DTime have the -- same representation.- type DTime = Double	-- [s] - -- Representation of signal function in initial state. -- (Naming: "TF" stands for Transition Function.) +-- | Signal function that transforms a signal carrying values of some type 'a'+-- into a signal carrying values of some type 'b'. You can think of it as+-- (Signal a -> Signal b). A signal is, conceptually, a+-- function from 'Time' to value. data SF a b = SF {sfTF :: a -> Transition a b}  @@ -1753,29 +1766,31 @@ -- Basic event sources ------------------------------------------------------------------------------ --- Event source that never occurs.+-- | Event source that never occurs. never :: SF a (Event b) never = SF {sfTF = \_ -> (sfNever, NoEvent)}  --- Event source with a single occurrence at time 0. The value of the event+-- | Event source with a single occurrence at time 0. The value of the event -- is given by the function argument. now :: b -> SF a (Event b) now b0 = (Event b0 --> never)  --- Event source with a single occurrence at or as soon after (local) time q+-- | Event source with a single occurrence at or as soon after (local) time /q/ -- as possible.-after :: Time -> b -> SF a (Event b)+after :: Time -- ^ The time /q/ after which the event should be produced+      -> b    -- ^ Value to produce at that time+      -> SF a (Event b) after q x = afterEach [(q,x)] ---- Event source with repeated occurrences with interval q.+-- | Event source with repeated occurrences with interval q. -- Note: If the interval is too short w.r.t. the sampling intervals, -- the result will be that events occur at every sample. However, no more -- than one event results from any sampling interval, thus avoiding an -- "event backlog" should sampling become more frequent at some later -- point in time.+ -- !!! 2005-03-30:  This is potentially a bit inefficient since we KNOW -- !!! (at this level) that the SF is going to be invarying. But afterEach -- !!! does NOT know this as the argument list may well be finite.@@ -2004,7 +2019,10 @@                                                    (x' : rxs)  --- A rising edge detector. Useful for things like detecting key presses.+-- | A rising edge detector. Useful for things like detecting key presses.+-- It is initialised as /up/, meaning that events occuring at time 0 will+-- not be detected.+ -- Note that we initialize the loop with state set to True so that there -- will not be an occurence at t0 in the logical time frame in which -- this is started.@@ -3126,10 +3144,33 @@ --			the reactimation loop and return to its caller. -- sf .........	Signal function to reactimate. -reactimate :: IO a-	      -> (Bool -> IO (DTime, Maybe a))-	      -> (Bool -> b -> IO Bool)-              -> SF a b+-- | Convenience function to run a signal function indefinitely, using+-- a IO actions to obtain new input and process the output.+--+-- This function first runs the initialization action, which provides the+-- initial input for the signal transformer at time 0.+--+-- Afterwards, an input sensing action is used to obtain new input (if any) and+-- the time since the last iteration. The argument to the input sensing function+-- indicates if it can block. If no new input is received, it is assumed to be+-- the same as in the last iteration.+--+-- After applying the signal function to the input, the actuation IO action+-- is executed. The first argument indicates if the output has changed, the second+-- gives the actual output). Actuation functions may choose to ignore the first+-- argument altogether. This action should return True if the reactimation+-- must stop, and False if it should continue.+--+-- Note that this becomes the program's /main loop/, which makes using this+-- function incompatible with GLUT, Gtk and other graphics libraries. It may also+-- impose a sizeable constraint in larger projects in which different subparts run+-- at different time steps. If you need to control the main+-- loop yourself for these or other reasons, use 'reactInit' and 'react'.++reactimate :: IO a                                -- ^ IO initialization action+	      -> (Bool -> IO (DTime, Maybe a))    -- ^ IO input sensing action+	      -> (Bool -> b -> IO Bool)           -- ^ IO actuaction (output processing) action+              -> SF a b                           -- ^ Signal function 	      -> IO () reactimate init sense actuate (SF {sfTF = tf0}) =     do@@ -3308,3 +3349,6 @@ -- 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!++-- Vim modeline+-- vim:set tabstop=8 expandtab:
src/FRP/Yampa/Event.hs view
@@ -94,20 +94,24 @@ -- Also note that it unfortunately is possible to partially break the -- abstractions through judicious use of e.g. snap and switching. +-- | A single possible event occurrence, that is, a value that may or may+-- not occur. Events are used to represent values that are not produced+-- continuously, such as mouse clicks (only produced when the mouse is clicked,+-- as opposed to mouse positions, which are always defined). data Event a = NoEvent | Event a deriving (Show) --- Make the NoEvent constructor available. Useful e.g. for initialization,+-- | Make the NoEvent constructor available. Useful e.g. for initialization, -- ((-->) & friends), and it's easily available anyway (e.g. mergeEvents []). noEvent :: Event a noEvent = NoEvent  --- Suppress any event in the first component of a pair.+-- | Suppress any event in the first component of a pair. noEventFst :: (Event a, b) -> (Event c, b) noEventFst (_, b) = (NoEvent, b)  --- Suppress any event in the second component of a pair.+-- | Suppress any event in the second component of a pair. noEventSnd :: (a, Event b) -> (a, Event c) noEventSnd (a, _) = (a, NoEvent) @@ -169,19 +173,22 @@ -- Utility functions similar to those available for Maybe ------------------------------------------------------------------------------ --- An event-based version of the maybe function.+-- | An event-based version of the maybe function. event :: a -> (b -> a) -> Event b -> a event a _ NoEvent   = a event _ f (Event b) = f b +-- | Extract the value from an event. Fails if there is no event. fromEvent :: Event a -> a fromEvent (Event a) = a fromEvent NoEvent   = usrErr "AFRP" "fromEvent" "Not an event." +-- | Tests whether the input represents an actual event. isEvent :: Event a -> Bool isEvent NoEvent   = False isEvent (Event _) = True +-- | Negation of 'isEvent'. isNoEvent :: Event a -> Bool isNoEvent = not . isEvent @@ -190,14 +197,16 @@ -- Event tagging ------------------------------------------------------------------------------ --- Tags an (occurring) event with a value ("replacing" the old value).+-- | Tags an (occurring) event with a value ("replacing" the old value). tag :: Event a -> b -> Event b e `tag` b = fmap (const b) e +-- | Tags an (occurring) event with a value ("replacing" the old value). Same+-- as 'tag' with the arguments swapped. tagWith :: b -> Event a -> Event b tagWith = flip tag --- Attaches an extra value to the value of an occurring event.+-- | Attaches an extra value to the value of an occurring event. attach :: Event a -> b -> Event (a, b) e `attach` b = fmap (\a -> (a, b)) e @@ -214,57 +223,58 @@ -- !!! Finally: mergeEvents is left-biased, but this is not reflected in -- !!! its name. --- Left-biased event merge.+-- | Left-biased event merge (always prefer left event, if present). lMerge :: Event a -> Event a -> Event a le `lMerge` re = event re Event le  --- Right-biased event merge.+-- | Right-biased event merge (always prefer right event, if present). rMerge :: Event a -> Event a -> Event a le `rMerge` re = event le Event re  --- Unbiased event merge: simultaneous occurrence is an error.+-- | Unbiased event merge: simultaneous occurrence is an error. merge :: Event a -> Event a -> Event a merge = mergeBy (usrErr "AFRP" "merge" "Simultaneous event occurrence.")  --- Event merge paramterezied on the conflict resolution function.+-- | Event merge parameterized by a conflict resolution function. mergeBy :: (a -> a -> a) -> Event a -> Event a -> Event a mergeBy _       NoEvent      NoEvent      = NoEvent mergeBy _       le@(Event _) NoEvent      = le mergeBy _       NoEvent      re@(Event _) = re mergeBy resolve (Event l)    (Event r)    = Event (resolve l r) ---- A generic event merge utility:+-- | A generic event merge-map utility that maps event occurrences,+-- merging the results. The first three arguments are mapping functions,+-- the third of which will only be used when both events are present.+-- Therefore, 'mergeBy' = 'mapMerge' 'id' 'id' mapMerge :: (a -> c) -> (b -> c) -> (a -> b -> c)  	    -> Event a -> Event b -> Event c-mapMerge _  _  _   NoEvent   NoEvent = NoEvent-mapMerge lf _  _   (Event l) NoEvent = Event (lf l)-mapMerge _  rf _   NoEvent  (Event r) = Event (rf r)+mapMerge _  _  _   NoEvent   NoEvent   = NoEvent+mapMerge lf _  _   (Event l) NoEvent   = Event (lf l)+mapMerge _  rf _   NoEvent   (Event r) = Event (rf r) mapMerge _  _  lrf (Event l) (Event r) = Event (lrf l r)  -- Merging of a list of events; foremost event has priority. mergeEvents :: [Event a] -> Event a mergeEvents = foldr lMerge NoEvent ---- Collects simultaneous event occurrences; no event if none.+-- | Collects simultaneous event occurrences; no event if none. catEvents :: [Event a] -> Event [a] catEvents eas = case [ a | Event a <- eas ] of 		    [] -> NoEvent 		    as -> Event as ---- Join (conjucntion) of two events.+-- | Join (conjucntion) of two events. Only produces an event+-- if both events exist. joinE :: Event a -> Event b -> Event (a,b) joinE NoEvent   _         = NoEvent joinE _         NoEvent   = NoEvent joinE (Event l) (Event r) = Event (l,r)  --- Split event carrying pairs into two events.+-- | Split event carrying pairs into two events. splitE :: Event (a,b) -> (Event a, Event b) splitE NoEvent       = (NoEvent, NoEvent) splitE (Event (a,b)) = (Event a, Event b)@@ -274,13 +284,14 @@ -- Event filtering ------------------------------------------------------------------------------ --- Filter out events that don't satisfy some predicate.+-- | Filter out events that don't satisfy some predicate. filterE :: (a -> Bool) -> Event a -> Event a-filterE p e@(Event a) = if (p a) then e else NoEvent+filterE p e@(Event a) = if p a then e else NoEvent filterE _ NoEvent     = NoEvent  --- Combined event mapping and filtering.+-- | Combined event mapping and filtering. Note: since 'Event' is a 'Functor',+-- see 'fmap' for a simpler version of this function with no filtering. mapFilterE :: (a -> Maybe b) -> Event a -> Event b mapFilterE _ NoEvent   = NoEvent mapFilterE f (Event a) = case f a of@@ -288,7 +299,7 @@ 			    Just b  -> Event b  --- Enable/disable event occurences based on an external condition.+-- | Enable/disable event occurences based on an external condition. gate :: Event a -> Bool -> Event a _ `gate` False = NoEvent e `gate` True  = e