elerea 2.3.0 → 2.4.0
raw patch · 3 files changed
+110/−3 lines, 3 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ FRP.Elerea.Simple: effectful :: IO (IO a) -> SignalGen (Signal a)
+ FRP.Elerea.Simple: effectful1 :: IO (t -> IO a) -> Signal t -> SignalGen (Signal a)
+ FRP.Elerea.Simple: effectful2 :: IO (t1 -> t2 -> IO a) -> Signal t1 -> Signal t2 -> SignalGen (Signal a)
+ FRP.Elerea.Simple: effectful3 :: IO (t1 -> t2 -> t3 -> IO a) -> Signal t1 -> Signal t2 -> Signal t3 -> SignalGen (Signal a)
+ FRP.Elerea.Simple: effectful4 :: IO (t1 -> t2 -> t3 -> t4 -> IO a) -> Signal t1 -> Signal t2 -> Signal t3 -> Signal t4 -> SignalGen (Signal a)
Files
- CHANGES +3/−0
- FRP/Elerea/Simple.hs +105/−1
- elerea.cabal +2/−2
CHANGES view
@@ -1,3 +1,6 @@+2.4.0 - 111111+* added effectful signals to assist library writers+ 2.3.0 - 110627 * reimplemented clocked variant in a correct and more efficient way
FRP/Elerea/Simple.hs view
@@ -28,6 +28,12 @@ , transfer2 , transfer3 , transfer4+ -- * Signals with side effects+ , effectful+ , effectful1+ , effectful2+ , effectful3+ , effectful4 -- * Random sources , noise , getRandom@@ -251,6 +257,10 @@ addSignal (const sample) (const (() <$ sample)) ref pool +-- | Auxiliary function.+memoise :: IORef (Phase a) -> a -> IO a+memoise ref x = writeIORef ref (Updated undefined x) >> return x+ -- | Memoising combinator. It can be used to cache results of -- applicative combinators in case they are used in several places. -- It is observationally equivalent to 'return' in the 'SignalGen'@@ -269,7 +279,7 @@ memo (S s) = SG $ \pool -> do ref <- newIORef (Ready undefined) - let sample = s >>= \x -> writeIORef ref (Updated undefined x) >> return x+ let sample = s >>= memoise ref addSignal (const sample) (const (() <$ sample)) ref pool @@ -474,6 +484,100 @@ transfer4 x0 f s1 s2 s3 s4 = mfix $ \sig -> do sig' <- delay x0 sig memo (liftM5 f s1 s2 s3 s4 sig')++-- | A signal that executes a given IO action once at every sampling.+-- The IO action is constructed by an initialiser.+--+-- In essence, this combinator provides cooperative multitasking+-- capabilities, and its primary purpose is to assist library writers+-- in wrapping effectful APIs as conceptually pure signals. If there+-- are several effectful signals in the system, their order of+-- execution is undefined and should not be relied on.+--+-- Example:+--+-- > do+-- > act <- start $ effectful $ do+-- > ref <- newIORef 0+-- > return $ do+-- > x <- readIORef ref+-- > putStrLn $ "Count: " ++ show x+-- > writeIORef ref $! x+1+-- > return ()+-- > replicateM_ 5 act+--+-- Output:+--+-- > Count: 0+-- > Count: 1+-- > Count: 2+-- > Count: 3+-- > Count: 4+effectful :: IO (IO a) -- ^ initialiser that yields the action to be executed repeatedly+ -> SignalGen (Signal a)+effectful gen = SG $ \pool -> do+ ref <- newIORef (Ready undefined)+ act <- gen++ let sample = act >>= memoise ref++ addSignal (const sample) (const (() <$ sample)) ref pool++-- | A signal that executes a parametric IO action once at every+-- sampling. The IO action is constructed by an initialiser, and the+-- parameter is supplied by another signal at every sampling step.+effectful1 :: IO (t -> IO a) -- ^ initialiser that yields the action to be executed repeatedly+ -> Signal t -- ^ parameter signal+ -> SignalGen (Signal a)+effectful1 gen (S s) = SG $ \pool -> do+ ref <- newIORef (Ready undefined)+ act <- gen++ let sample = s >>= act >>= memoise ref++ addSignal (const sample) (const (() <$ sample)) ref pool++-- | Like 'effectful1', but with two parameter signals.+effectful2 :: IO (t1 -> t2 -> IO a) -- ^ initialiser that yields the action to be executed repeatedly+ -> Signal t1 -- ^ parameter signal 1+ -> Signal t2 -- ^ parameter signal 2+ -> SignalGen (Signal a)+effectful2 gen (S s1) (S s2) = SG $ \pool -> do+ ref <- newIORef (Ready undefined)+ act <- gen++ let sample = join (liftM2 act s1 s2) >>= memoise ref++ addSignal (const sample) (const (() <$ sample)) ref pool++-- | Like 'effectful1', but with three parameter signals.+effectful3 :: IO (t1 -> t2 -> t3 -> IO a) -- ^ initialiser that yields the action to be executed repeatedly+ -> Signal t1 -- ^ parameter signal 1+ -> Signal t2 -- ^ parameter signal 2+ -> Signal t3 -- ^ parameter signal 3+ -> SignalGen (Signal a)+effectful3 gen (S s1) (S s2) (S s3) = SG $ \pool -> do+ ref <- newIORef (Ready undefined)+ act <- gen++ let sample = join (liftM3 act s1 s2 s3) >>= memoise ref++ addSignal (const sample) (const (() <$ sample)) ref pool++-- | Like 'effectful1', but with four parameter signals.+effectful4 :: IO (t1 -> t2 -> t3 -> t4 -> IO a) -- ^ initialiser that yields the action to be executed repeatedly+ -> Signal t1 -- ^ parameter signal 1+ -> Signal t2 -- ^ parameter signal 2+ -> Signal t3 -- ^ parameter signal 3+ -> Signal t4 -- ^ parameter signal 4+ -> SignalGen (Signal a)+effectful4 gen (S s1) (S s2) (S s3) (S s4) = SG $ \pool -> do+ ref <- newIORef (Ready undefined)+ act <- gen++ let sample = join (liftM4 act s1 s2 s3 s4) >>= memoise ref++ addSignal (const sample) (const (() <$ sample)) ref pool -- | A random signal. --
elerea.cabal view
@@ -1,5 +1,5 @@ Name: elerea-Version: 2.3.0+Version: 2.4.0 Cabal-Version: >= 1.2 Synopsis: A minimalistic FRP library Category: reactivity, FRP@@ -38,7 +38,7 @@ (<http://sgate.emt.bme.hu/documents/patai/publications/PataiWFLP2010.pdf>). Author: Patai Gergely-Maintainer: Patai Gergely (patai@iit.bme.hu)+Maintainer: Patai Gergely (patai.gergely@gmail.com) Copyright: (c) 2009-2011, Patai Gergely License: BSD3 License-File: LICENSE