reactive-banana-automation 0.2.0 → 0.3.0
raw patch · 4 files changed
+64/−29 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Reactive.Banana.Automation: type EventSource a = (AddHandler a, a -> IO ())
+ Reactive.Banana.Automation: automationStepper :: a -> Event a -> MomentAutomation (Behavior a)
+ Reactive.Banana.Automation: data EventSource a v
+ Reactive.Banana.Automation: fromEventSource :: EventSource a v -> v
+ Reactive.Banana.Automation: newEventSource :: v -> IO (EventSource a v)
+ Reactive.Banana.Automation: sensedEventBehavior :: Event (Sensed a) -> MomentAutomation (Behavior (Sensed a))
+ Reactive.Banana.Automation: sensorUnavailable :: EventSource (Sensed a) v -> IO ()
- Reactive.Banana.Automation: (=:) :: EventSource (Sensed a) -> a -> IO ()
+ Reactive.Banana.Automation: (=:) :: EventSource (Sensed a) v -> a -> IO ()
- Reactive.Banana.Automation: clockSignal :: Timestamp t => EventSource (ClockSignal t) -> IO ()
+ Reactive.Banana.Automation: clockSignal :: Timestamp t => EventSource (ClockSignal t) v -> IO ()
- Reactive.Banana.Automation: clockSignalAt :: Timestamp t => t -> EventSource (ClockSignal t) -> IO ()
+ Reactive.Banana.Automation: clockSignalAt :: Timestamp t => t -> EventSource (ClockSignal t) v -> IO ()
- Reactive.Banana.Automation: clockSignalBehavior :: Timestamp t => EventSource (ClockSignal t) -> MomentAutomation (Behavior (Maybe (ClockSignal t)))
+ Reactive.Banana.Automation: clockSignalBehavior :: Timestamp t => EventSource (ClockSignal t) v -> MomentAutomation (Behavior (Maybe (ClockSignal t)))
- Reactive.Banana.Automation: getEventFrom :: EventSource a -> MomentAutomation (Event a)
+ Reactive.Banana.Automation: getEventFrom :: EventSource a v -> MomentAutomation (Event a)
- Reactive.Banana.Automation: gotEvent :: EventSource a -> a -> IO ()
+ Reactive.Banana.Automation: gotEvent :: EventSource a v -> a -> IO ()
- Reactive.Banana.Automation: sensed :: EventSource (Sensed a) -> a -> IO ()
+ Reactive.Banana.Automation: sensed :: EventSource (Sensed a) v -> a -> IO ()
- Reactive.Banana.Automation: sensedAt :: Timestamp t => t -> EventSource (Sensed (Timestamped t a)) -> a -> IO ()
+ Reactive.Banana.Automation: sensedAt :: Timestamp t => t -> EventSource (Sensed (Timestamped t a)) v -> a -> IO ()
- Reactive.Banana.Automation: sensedBehavior :: EventSource (Sensed a) -> MomentAutomation (Behavior (Sensed a))
+ Reactive.Banana.Automation: sensedBehavior :: EventSource (Sensed a) v -> MomentAutomation (Behavior (Sensed a))
- Reactive.Banana.Automation: sensedEvent :: EventSource (Sensed a) -> MomentAutomation (Event a)
+ Reactive.Banana.Automation: sensedEvent :: EventSource (Sensed a) v -> MomentAutomation (Event a)
- Reactive.Banana.Automation: sensedNow :: Timestamp t => EventSource (Sensed (Timestamped t a)) -> a -> IO ()
+ Reactive.Banana.Automation: sensedNow :: Timestamp t => EventSource (Sensed (Timestamped t a)) v -> a -> IO ()
- Reactive.Banana.Automation.Examples: Sensors :: EventSource (Sensed Double) -> EventSource (Sensed (Timestamped POSIXTime Bool)) -> EventSource (ClockSignal LocalTime) -> EventSource (Sensed ()) -> Sensors
+ Reactive.Banana.Automation.Examples: Sensors :: EventSource (Sensed Double) () -> EventSource (Sensed (Timestamped POSIXTime Bool)) () -> EventSource (ClockSignal LocalTime) () -> EventSource (Sensed ()) () -> Sensors
- Reactive.Banana.Automation.Examples: [clock] :: Sensors -> EventSource (ClockSignal LocalTime)
+ Reactive.Banana.Automation.Examples: [clock] :: Sensors -> EventSource (ClockSignal LocalTime) ()
- Reactive.Banana.Automation.Examples: [fridgeTemperature] :: Sensors -> EventSource (Sensed Double)
+ Reactive.Banana.Automation.Examples: [fridgeTemperature] :: Sensors -> EventSource (Sensed Double) ()
- Reactive.Banana.Automation.Examples: [motionSensor] :: Sensors -> EventSource (Sensed (Timestamped POSIXTime Bool))
+ Reactive.Banana.Automation.Examples: [motionSensor] :: Sensors -> EventSource (Sensed (Timestamped POSIXTime Bool)) ()
- Reactive.Banana.Automation.Examples: [rainGaugeTipSensor] :: Sensors -> EventSource (Sensed ())
+ Reactive.Banana.Automation.Examples: [rainGaugeTipSensor] :: Sensors -> EventSource (Sensed ()) ()
Files
- CHANGELOG +9/−0
- Reactive/Banana/Automation.hs +46/−19
- Reactive/Banana/Automation/Examples.hs +8/−9
- reactive-banana-automation.cabal +1/−1
CHANGELOG view
@@ -1,3 +1,12 @@+reactive-banana-automation (0.3.0) upstream; urgency=medium++ * EventSource is now a data type with an extra value for expansion.+ (API change)+ * Added newEventSource, sensorUnavailable, sensedEventBehavior,+ and automationStepper.++ -- Joey Hess <id@joeyh.name> Sat, 05 May 2018 19:27:56 -0400+ reactive-banana-automation (0.2.0) upstream; urgency=medium * Automation is now a newtype. (API change)
Reactive/Banana/Automation.hs view
@@ -23,6 +23,8 @@ observeAutomation, -- * Events EventSource,+ newEventSource,+ fromEventSource, gotEvent, getEventFrom, onEvent,@@ -32,6 +34,9 @@ sensedBehavior, sensed, (=:),+ sensorUnavailable,+ sensedEventBehavior,+ automationStepper, -- * Time Timestamped(..), Timestamp(..),@@ -72,7 +77,7 @@ -- run as needed to keep the temperature in a safe range, while -- minimizing compressor starts. ----- > data Sensors = Sensors { fridgeTemperature :: EventSource (Sensed Double) }+-- > data Sensors = Sensors { fridgeTemperature :: EventSource (Sensed Double) () } -- > data Actuators = FridgePower PowerChange deriving (Show) -- > -- > fridge :: Automation Sensors Actuators@@ -138,7 +143,7 @@ -- Continuing the above example of a fridge, here's how to run it: -- -- > mkSensors :: IO Sensors--- > mkSensors = Sensors <$> newAddHandler+-- > mkSensors = Sensors <$> newEventSource () -- > -- > driveActuators :: Actuators -> IO () -- > driveActuators = print@@ -196,17 +201,29 @@ return runner -- | A source of events.-type EventSource a = (AddHandler a, a -> IO ())+--+-- `v` is unused by this library, but is provided in case you+-- need a way to track some extra data about an EventSource such as, for+-- example, the timestamp of the most recent event.+data EventSource a v = EventSource+ { getEventSource :: (AddHandler a, a -> IO ())+ , fromEventSource :: v+ -- ^ Get extra data from an EventSource.+ } -addHandler :: EventSource a -> AddHandler a-addHandler = fst+-- | Construct a new EventSource.+newEventSource :: v -> IO (EventSource a v)+newEventSource v = EventSource <$> newAddHandler <*> pure v +addHandler :: EventSource a v -> AddHandler a+addHandler = fst . getEventSource+ -- | Call this to trigger an event.-gotEvent :: EventSource a -> a -> IO ()-gotEvent = snd+gotEvent :: EventSource a v -> a -> IO ()+gotEvent = snd . getEventSource -- | Get an Event from an EventSource.-getEventFrom :: EventSource a -> MomentAutomation (Event a)+getEventFrom :: EventSource a v -> MomentAutomation (Event a) getEventFrom = MomentAutomation . fromAddHandler . addHandler -- | Runs an action when an event occurs.@@ -224,7 +241,7 @@ -- -- The Event only contains values when the sensor provided a reading, -- not times when it was unavailable.-sensedEvent :: EventSource (Sensed a) -> MomentAutomation (Event a)+sensedEvent :: EventSource (Sensed a) v -> MomentAutomation (Event a) sensedEvent s = do e <- getEventFrom s return $ filterJust $ flip fmap e $ \case@@ -232,22 +249,32 @@ Sensed a -> Just a -- | Create a Behavior from sensed values.-sensedBehavior :: EventSource (Sensed a) -> MomentAutomation (Behavior (Sensed a))-sensedBehavior s = - MomentAutomation . stepper SensorUnavailable =<< getEventFrom s+sensedBehavior :: EventSource (Sensed a) v -> MomentAutomation (Behavior (Sensed a))+sensedBehavior s = sensedEventBehavior =<< getEventFrom s +sensedEventBehavior :: Event (Sensed a) -> MomentAutomation (Behavior (Sensed a))+sensedEventBehavior = automationStepper SensorUnavailable++-- | `stepper` lifted into `MomentAutomation`+automationStepper :: a -> Event a -> MomentAutomation (Behavior a)+automationStepper a e = MomentAutomation $ stepper a e+ -- | Call when a sensor has sensed a value. -- -- > getFridgeTemperature >>= sensed (fridgeTemperature sensors)-sensed :: EventSource (Sensed a) -> a -> IO ()+sensed :: EventSource (Sensed a) v -> a -> IO () sensed s = gotEvent s . Sensed -- | Same as `sensed` -- -- > fridgeTemperature sensors =: 0-(=:) :: EventSource (Sensed a) -> a -> IO ()+(=:) :: EventSource (Sensed a) v -> a -> IO () (=:) = sensed +-- | Call when a sensor is unavailable.+sensorUnavailable :: EventSource (Sensed a) v -> IO ()+sensorUnavailable s = gotEvent s SensorUnavailable+ -- | A timestamped value. -- -- In reactive-banana, an `Event` is tagged with its time of occurrence,@@ -289,13 +316,13 @@ -- | Call when a sensor has sensed a value, which will be `Timestamped` with -- the current time.-sensedNow :: Timestamp t => EventSource (Sensed (Timestamped t a)) -> a -> IO ()+sensedNow :: Timestamp t => EventSource (Sensed (Timestamped t a)) v -> a -> IO () sensedNow es a = do now <- getCurrentTimestamp gotEvent es (Sensed (Timestamped now a)) -- | Call when a sensor sensed a value with a particular timestamp.-sensedAt :: Timestamp t => t -> EventSource (Sensed (Timestamped t a)) -> a -> IO ()+sensedAt :: Timestamp t => t -> EventSource (Sensed (Timestamped t a)) v -> a -> IO () sensedAt ts es a = gotEvent es (Sensed (Timestamped ts a)) -- | Given a `Timestamped` `Event` and a function, produces an `Event`@@ -332,16 +359,16 @@ -- | Call repeatedly to feed a clock signal to an `Automation` -- that needs to know what time it is.-clockSignal :: Timestamp t => EventSource (ClockSignal t) -> IO ()+clockSignal :: Timestamp t => EventSource (ClockSignal t) v -> IO () clockSignal es = gotEvent es . ClockSignal =<< getCurrentTimestamp -- | Call to feed a particular time to an `Automation`.-clockSignalAt :: Timestamp t => t -> EventSource (ClockSignal t) -> IO ()+clockSignalAt :: Timestamp t => t -> EventSource (ClockSignal t) v -> IO () clockSignalAt t es = gotEvent es (ClockSignal t) -- | Create a Behavior from a ClockSignal. It will initially be Nothing, -- and then updates with each incoming clock signal.-clockSignalBehavior :: Timestamp t => EventSource (ClockSignal t) -> MomentAutomation (Behavior (Maybe (ClockSignal t)))+clockSignalBehavior :: Timestamp t => EventSource (ClockSignal t) v -> MomentAutomation (Behavior (Maybe (ClockSignal t))) clockSignalBehavior s = MomentAutomation . stepper Nothing =<< fmap Just <$> getEventFrom s
Reactive/Banana/Automation/Examples.hs view
@@ -6,7 +6,6 @@ module Reactive.Banana.Automation.Examples where import Reactive.Banana-import Reactive.Banana.Frameworks import Reactive.Banana.Automation import Data.Time.Clock.POSIX import Data.Time.LocalTime@@ -15,10 +14,10 @@ -- | We'll use a single Sensors type containing all the sensors -- used by the examples below. data Sensors = Sensors- { fridgeTemperature :: EventSource (Sensed Double)- , motionSensor :: EventSource (Sensed (Timestamped POSIXTime Bool))- , clock :: EventSource (ClockSignal LocalTime)- , rainGaugeTipSensor :: EventSource (Sensed ())+ { fridgeTemperature :: EventSource (Sensed Double) ()+ , motionSensor :: EventSource (Sensed (Timestamped POSIXTime Bool)) ()+ , clock :: EventSource (ClockSignal LocalTime) ()+ , rainGaugeTipSensor :: EventSource (Sensed ()) () } -- | And a single Actuators type containing all the actuators used by the@@ -33,10 +32,10 @@ -- | For running the examples, you'll need this, to construct a `Sensors` mkSensors :: IO Sensors mkSensors = Sensors- <$> newAddHandler- <*> newAddHandler- <*> newAddHandler- <*> newAddHandler+ <$> newEventSource ()+ <*> newEventSource ()+ <*> newEventSource ()+ <*> newEventSource () -- | A fridge, containing the `fridgeTemperature` sensor and with -- its power controlled by the `FridgePower` actuator.
reactive-banana-automation.cabal view
@@ -1,5 +1,5 @@ Name: reactive-banana-automation-Version: 0.2.0+Version: 0.3.0 Cabal-Version: >= 1.8 License: AGPL-3 Maintainer: Joey Hess <id@joeyh.name>