1 {-# LANGUAGE Arrows #-}
3 module RMCA.Auxiliary.Yampa where
7 import RMCA.Auxiliary.Misc
11 countTo :: (Integral b) => b -> SF (Event a) (Event b)
12 countTo n = count >>^ filterE (== n)
14 -- | Synchonizes two event sources. An event on the first source will be delayed until an event occurs on the second.
17 -- Event a => . . 1 . . . . 2 . . . 3 . . 4 . . . . . 5 . . 6 . . . . .
18 -- Event b => . a . . . b . . . c . . . . . . d . e . f . . . . . g . .
19 -- wairFor => . . . . . 1 . . . 2 . . . . . . 4 . . . 5 . . . . . 6 . .
21 waitForEvent :: SF (Event a, Event b) (Event a)
22 waitForEvent = proc (ea,eb) -> do
23 em <- arr $ uncurry $ mapMerge Left Right (\_ b -> Right b) -< (ea,eb)
24 hob <- dAccumHoldBy accumulator NoEvent -< em
25 returnA -< eb *> (ea `lMerge` hob)
26 where accumulator :: Event a -> Either a b -> Event a
27 accumulator _ (Left a) = Event a
28 accumulator _ (Right _) = NoEvent
29 --accumulator _ (Right b) =
32 waitForEvent :: SF (Event b, Event a) (Event b)
33 waitForEvent = proc (eb,ea) -> do
35 es' <- iPre NoEvent -< es
36 es <- rSwitch waitAux -< ((eb,ea),es' `tag` waitAux)
38 where waitAux = proc (eb,ea) -> do
39 --ea' <- (if b then notYet else identity) -< ea
40 eb' <- accumHoldBy (\_ b -> Event b) NoEvent -< eb
43 -- | 'stepBack' contains its previous argument as its output. Because it's hard to define it at time 0, it's wrapped up in a 'Maybe'.
44 stepBack :: SF a (Maybe a)
45 stepBack = sscan f (Nothing, Nothing) >>^ snd
46 where f :: (Maybe a, Maybe a) -> a -> (Maybe a, Maybe a)
47 f (Nothing,_) x' = (Just x', Nothing)
48 f (Just x, _) x' = (Just x', Just x)
50 -- | Like 'stepBack' but the output value is always defined and is equal to the input at time 0.
52 stepBack' = proc x -> do
54 returnA -< fromMaybe x x'
56 -- | Throws an 'Event' when the incoming signal change. The 'Event' is tagged with the new value.
57 onChange :: (Eq a) => SF a (Event a)
58 onChange = proc x -> do
61 | isNothing x' = NoEvent
62 | otherwise = let x'' = fromJust x' in
63 if x'' == x then NoEvent else Event x
64 returnA -< makeEvent x x'
66 -- | Similar to 'onChange' but contains its initial value in the first
68 onChange' :: (Eq a) => SF a (Event a)
69 onChange' = proc x -> do
71 -- If it's the first value, throw an Event, else behave like onChange.
73 | isNothing x' = Event x
74 | otherwise = let x'' = fromJust x' in
75 if x'' == x then NoEvent else Event x
76 returnA -< makeEvent x x'
78 -- | Integrates some variable modulo something.
79 integralMod :: (Real a, VectorSpace a s) => a -> SF a a
80 integralMod x = intMod' 0
81 where intMod' x0 = switch (intMod'' x0) (\y -> intMod' (y - x))
82 intMod'' x0 = proc t -> do
83 it <- (+ x0) ^<< integral -< t
84 es <- edgeBy (\_ y -> maybeIf (y > x) $> y) 0 -< it
89 -- | Generates a sine function whose period is given as a varying input.
90 varFreqSine :: SF DTime Double
91 varFreqSine = sin ^<< (2*pi*) ^<< integralMod 1 <<^ (1/)
93 -- | Generates an 'Event' with a regular period, which is given as an input to the signal function.
94 repeatedlyS :: a -> SF DTime (Event a)
95 repeatedlyS x = edgeBy (\a b -> maybeIf (a * b < 0) $> x) 0
96 <<< varFreqSine <<^ (2*)
98 repeatedlyS' :: a -> SF DTime (Event a)
99 repeatedlyS' x = (repeatedlyS x &&& now x) >>> arr (uncurry lMerge)
102 -- = Curry and uncurry functions