1 {-# LANGUAGE Arrows, FlexibleContexts, MultiParamTypeClasses #-}
3 module RMCA.Auxiliary where
8 import Data.ReactiveValue
11 --------------------------------------------------------------------------------
13 --------------------------------------------------------------------------------
15 bound :: (Ord a) => (a, a) -> a -> a
21 fromMaybeM_ :: (Monad m) => Maybe (m ()) -> m ()
22 fromMaybeM_ = fromMaybe (return ())
24 --------------------------------------------------------------------------------
26 --------------------------------------------------------------------------------
28 -- stepBack contains its previous argument as its output. Because it's
29 -- hard to define it at time 0, it's wrapped up in a Maybe.
30 stepBack :: SF a (Maybe a)
31 stepBack = sscan f (Nothing, Nothing) >>^ snd
32 where f :: (Maybe a, Maybe a) -> a -> (Maybe a, Maybe a)
33 f (Nothing,_) x' = (Just x', Nothing)
34 f (Just x, _) x' = (Just x', Just x)
36 -- Just like stepBack but the output value is always defined and is
37 -- equal to the input at time 0.
39 stepBack' = proc x -> do
41 returnA -< fromMaybe x x'
43 -- Throws an Event when the incoming signal change. The Event is
44 -- tagged with the new value.
45 onChange :: (Eq a) => SF a (Event a)
46 onChange = proc x -> do
49 | isNothing x' = NoEvent
50 | otherwise = let x'' = fromJust x' in
51 if x'' == x then NoEvent else Event x
52 returnA -< makeEvent x x'
54 varFreqSine :: SF DTime Double
55 varFreqSine = sin ^<< (2*pi*) ^<< integral <<^ (1/)
57 repeatedlyS :: a -> SF DTime (Event a)
58 repeatedlyS x = proc dt -> do
59 (sw,sw') <- (identity &&& stepBack) <<< varFreqSine -< 2*dt
60 edgeTag x <<^ maybe True (< 0) -< (*) <$> return sw <*> sw'
62 -- Similar to onChange but contains its initial value in the first
64 onChange' :: (Eq a) => SF a (Event a)
65 onChange' = proc x -> do
67 -- If it's the first value, throw an Event, else behave like onChange.
69 | isNothing x' = Event x
70 | otherwise = let x'' = fromJust x' in
71 if x'' == x then NoEvent else Event x
72 returnA -< makeEvent x x'
74 --------------------------------------------------------------------------------
76 --------------------------------------------------------------------------------
78 newCBMVarRW :: a -> IO (ReactiveFieldReadWrite IO a)
81 let getter = readCBMVar mvar
82 setter = writeCBMVar mvar
83 notifier = installCallbackCBMVar mvar
84 return $ ReactiveFieldReadWrite setter getter notifier
86 reactiveValueAppend :: (Monoid b, ReactiveValueReadWrite a b m) =>
88 reactiveValueAppend rv v = do ov <- reactiveValueRead rv
89 reactiveValueWrite rv (ov `mappend` v)
91 emptyRW :: (Monoid b, ReactiveValueReadWrite a b m) => a -> m b
93 val <- reactiveValueRead rv
94 reactiveValueWrite rv mempty
97 -- Update when the value is an Event. It would be nice to have that
98 -- even for Maybe as well.
99 (>:>) :: (ReactiveValueRead a (Event b) IO, ReactiveValueWrite c b IO) =>
101 eventRV >:> rv = reactiveValueOnCanRead eventRV syncOnEvent
102 where syncOnEvent = do
103 erv <- reactiveValueRead eventRV
104 when (isEvent erv) $ reactiveValueWrite rv $ fromEvent erv
107 , ReactiveValueWrite a b m
108 , ReactiveValueWrite c d m
109 , ReactiveValueWrite e f m) =>
110 (i -> (b,d,f)) -> a -> c -> e -> ReactiveFieldWrite m i
111 liftW3 f a b c = ReactiveFieldWrite setter
114 reactiveValueWrite a x1
115 reactiveValueWrite b x2
116 reactiveValueWrite c x3
118 liftRW3 :: ( ReactiveValueReadWrite a b m
119 , ReactiveValueReadWrite c d m
120 , ReactiveValueReadWrite e f m) =>
121 BijectiveFunc i (b,d,f) -> a -> c -> e -> ReactiveFieldReadWrite m i
123 ReactiveFieldReadWrite setter getter notifier
124 where ReactiveFieldRead getter notifier = liftR3 (curry3 f2) a b c
125 ReactiveFieldWrite setter = liftW3 f1 a b c
126 (f1, f2) = (direct bij, inverse bij)
128 liftR4 :: ( ReactiveValueRead a b m
129 , ReactiveValueRead c d m
130 , ReactiveValueRead e f m
131 , ReactiveValueRead g h m) =>
132 (b -> d -> f -> h -> i) -> a -> c -> e -> g -> ReactiveFieldRead m i
133 liftR4 f a b c d = ReactiveFieldRead getter notifier
135 x1 <- reactiveValueRead a
136 x2 <- reactiveValueRead b
137 x3 <- reactiveValueRead c
138 x4 <- reactiveValueRead d
139 return $ f x1 x2 x3 x4
141 reactiveValueOnCanRead a p
142 reactiveValueOnCanRead b p
143 reactiveValueOnCanRead c p
144 reactiveValueOnCanRead d p
147 , ReactiveValueWrite a b m
148 , ReactiveValueWrite c d m
149 , ReactiveValueWrite e f m
150 , ReactiveValueWrite g h m) =>
151 (i -> (b,d,f,h)) -> a -> c -> e -> g -> ReactiveFieldWrite m i
152 liftW4 f a b c d = ReactiveFieldWrite setter
154 let (x1,x2,x3,x4) = f x
155 reactiveValueWrite a x1
156 reactiveValueWrite b x2
157 reactiveValueWrite c x3
158 reactiveValueWrite d x4
160 liftRW4 :: ( ReactiveValueReadWrite a b m
161 , ReactiveValueReadWrite c d m
162 , ReactiveValueReadWrite e f m
163 , ReactiveValueReadWrite g h m) =>
164 BijectiveFunc i (b,d,f,h) -> a -> c -> e -> g
165 -> ReactiveFieldReadWrite m i
166 liftRW4 bij a b c d =
167 ReactiveFieldReadWrite setter getter notifier
168 where ReactiveFieldRead getter notifier = liftR4 (curry4 f2) a b c d
169 ReactiveFieldWrite setter = liftW4 f1 a b c d
170 (f1, f2) = (direct bij, inverse bij)
172 liftR5 :: ( ReactiveValueRead a b m
173 , ReactiveValueRead c d m
174 , ReactiveValueRead e f m
175 , ReactiveValueRead g h m
176 , ReactiveValueRead i j m) =>
177 (b -> d -> f -> h -> j -> k) -> a -> c -> e -> g -> i
178 -> ReactiveFieldRead m k
179 liftR5 f a b c d e = ReactiveFieldRead getter notifier
181 x1 <- reactiveValueRead a
182 x2 <- reactiveValueRead b
183 x3 <- reactiveValueRead c
184 x4 <- reactiveValueRead d
185 x5 <- reactiveValueRead e
186 return $ f x1 x2 x3 x4 x5
188 reactiveValueOnCanRead a p
189 reactiveValueOnCanRead b p
190 reactiveValueOnCanRead c p
191 reactiveValueOnCanRead d p
192 reactiveValueOnCanRead e p
195 , ReactiveValueWrite a b m
196 , ReactiveValueWrite c d m
197 , ReactiveValueWrite e f m
198 , ReactiveValueWrite g h m
199 , ReactiveValueWrite i j m) =>
200 (k -> (b,d,f,h,j)) -> a -> c -> e -> g -> i -> ReactiveFieldWrite m k
201 liftW5 f a b c d e = ReactiveFieldWrite setter
203 let (x1,x2,x3,x4,x5) = f x
204 reactiveValueWrite a x1
205 reactiveValueWrite b x2
206 reactiveValueWrite c x3
207 reactiveValueWrite d x4
208 reactiveValueWrite e x5
210 liftRW5 :: ( ReactiveValueReadWrite a b m
211 , ReactiveValueReadWrite c d m
212 , ReactiveValueReadWrite e f m
213 , ReactiveValueReadWrite g h m
214 , ReactiveValueReadWrite i j m) =>
215 BijectiveFunc k (b,d,f,h,j) -> a -> c -> e -> g -> i
216 -> ReactiveFieldReadWrite m k
217 liftRW5 bij a b c d e =
218 ReactiveFieldReadWrite setter getter notifier
219 where ReactiveFieldRead getter notifier = liftR5 (curry5 f2) a b c d e
220 ReactiveFieldWrite setter = liftW5 f1 a b c d e
221 (f1, f2) = (direct bij, inverse bij)
223 --------------------------------------------------------------------------------
224 -- Curry and uncurry functions
225 --------------------------------------------------------------------------------
227 curry3 :: ((a,b,c) -> d) -> a -> b -> c -> d
228 curry3 f a b c = f (a,b,c)
230 uncurry3 :: (a -> b -> c -> d) -> (a,b,c) -> d
231 uncurry3 f (a,b,c) = f a b c
233 curry4 :: ((a,b,c,d) -> e) -> a -> b -> c -> d -> e
234 curry4 f a b c d = f (a,b,c,d)
236 uncurry4 :: (a -> b -> c -> d -> e) -> (a,b,c,d) -> e
237 uncurry4 f (a,b,c,d) = f a b c d
239 curry5 :: ((a,b,c,d,e) -> f) -> a -> b -> c -> d -> e -> f
240 curry5 f a b c d e = f (a,b,c,d,e)
242 uncurry5 :: (a -> b -> c -> d -> e -> f) -> (a,b,c,d,e) -> f
243 uncurry5 f (a,b,c,d,e) = f a b c d e