reflex 0.6.4.1 → 0.7.0.0
raw patch · 11 files changed
+112/−27 lines, 11 filesnew-uploader
Files
- ChangeLog.md +9/−0
- README.md +8/−2
- reflex.cabal +1/−1
- src/Reflex/BehaviorWriter/Base.hs +3/−3
- src/Reflex/BehaviorWriter/Class.hs +11/−5
- src/Reflex/FastWeak.hs +10/−0
- src/Reflex/PerformEvent/Class.hs +6/−0
- src/Reflex/Profiled.hs +53/−1
- src/Reflex/Query/Class.hs +5/−5
- src/Reflex/Spider/Internal.hs +0/−10
- src/Reflex/TriggerEvent/Class.hs +6/−0
ChangeLog.md view
@@ -1,5 +1,14 @@ # Revision history for reflex +## 0.7.0.0++* Add lifting instances for most classes to `Reflex.Profiled.Profiled`. ([#398](https://github.com/reflex-frp/reflex/pull/398))+* Class `MonadQuery t q m` now has a `Monad m` superclass constraint. ([#400](https://github.com/reflex-frp/reflex/pull/400))+* **(Breaking change)** Rename class `MonadBehaviorWriter` -> `BehaviorWriter` for consistency with `EventWriter`/`DynamicWriter`. ([#401](https://github.com/reflex-frp/reflex/pull/401))+* Introduce deprecated alias `MonadBehaviorWriter = BehaviorWriter`. ([#401](https://github.com/reflex-frp/reflex/pull/401))+* Fix bug in spider where event subscriptions would be prematurely finalized due to over-aggressive inlining. ([#409](https://github.com/reflex-frp/reflex/pull/409))+* Add instances of `PerformEvent` and `TriggerEvent` for `MaybeT`. ([#395](https://github.com/reflex-frp/reflex/pull/395))+ ## 0.6.4.1 * Fix a bug in the Reflex Profiled transformer where
README.md view
@@ -21,5 +21,11 @@ ### Hacking -Use the `./scripts/hack-on reflex` script in [Reflex Platform](https://github.com/reflex-frp/reflex-platform) to checkout the source code of `reflex` locally in `reflex-platform/reflex` directory.-Then do modifications to the source in place, and use the `./try-reflex` or `./scripts/work-on` scripts to create the shell to test your changes.+From the root of a [Reflex+Platform](https://github.com/reflex-frp/reflex-platform) checkout, run+`./scripts/hack-on haskell-overlays/reflex-packages/dep/reflex`. This+will check out the reflex source code into the+`haskell-overlays/reflex-packages/dep/reflex` directory. You can then+point that checkout at your fork, make changes, etc. Use the+`./try-reflex` or `./scripts/work-on` scripts to start a shell in+which you can test your changes.
reflex.cabal view
@@ -1,5 +1,5 @@ Name: reflex-Version: 0.6.4.1+Version: 0.7.0.0 Synopsis: Higher-order Functional Reactive Programming Description: Reflex is a high-performance, deterministic, higher-order Functional Reactive Programming system License: BSD3
src/Reflex/BehaviorWriter/Base.hs view
@@ -1,6 +1,6 @@ {-| Module: Reflex.BehaviorWriter.Base-Description: Implementation of MonadBehaviorWriter+Description: Implementation of BehaviorWriter -} {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleInstances #-}@@ -46,7 +46,7 @@ import Reflex.Requester.Class import Reflex.TriggerEvent.Class --- | A basic implementation of 'MonadBehaviorWriter'.+-- | A basic implementation of 'BehaviorWriter'. newtype BehaviorWriterT t w m a = BehaviorWriterT { unBehaviorWriterT :: StateT [Behavior t w] m a } deriving (Functor, Applicative, Monad, MonadIO, MonadFix, MonadAsyncException, MonadException) -- The list is kept in reverse order @@ -89,7 +89,7 @@ newEventWithTrigger = lift . newEventWithTrigger newFanEventWithTrigger f = lift $ newFanEventWithTrigger f -instance (Monad m, Monoid w, Reflex t) => MonadBehaviorWriter t w (BehaviorWriterT t w m) where+instance (Monad m, Monoid w, Reflex t) => BehaviorWriter t w (BehaviorWriterT t w m) where tellBehavior w = BehaviorWriterT $ modify (w :) instance MonadReader r m => MonadReader r (BehaviorWriterT t w m) where
src/Reflex/BehaviorWriter/Class.hs view
@@ -1,8 +1,9 @@ {-| Module: Reflex.BehaviorWriter.Class-Description: This module defines the 'MonadBehaviorWriter' class+Description: This module defines the 'BehaviorWriter' class -} {-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE UndecidableInstances #-}@@ -10,16 +11,21 @@ {-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-} #endif module Reflex.BehaviorWriter.Class- ( MonadBehaviorWriter (..)+ ( MonadBehaviorWriter+ , BehaviorWriter(..) ) where import Control.Monad.Reader (ReaderT, lift) import Reflex.Class (Behavior) --- | 'MonadBehaviorWriter' efficiently collects 'Behavior' values using 'tellBehavior'+{-# DEPRECATED MonadBehaviorWriter "Use 'BehaviorWriter' instead" #-}+-- | Type synonym for 'BehaviorWriter'+type MonadBehaviorWriter = BehaviorWriter++-- | 'BehaviorWriter' efficiently collects 'Behavior' values using 'tellBehavior' -- and combines them monoidally to provide a 'Behavior' result.-class (Monad m, Monoid w) => MonadBehaviorWriter t w m | m -> t w where+class (Monad m, Monoid w) => BehaviorWriter t w m | m -> t w where tellBehavior :: Behavior t w -> m () -instance MonadBehaviorWriter t w m => MonadBehaviorWriter t w (ReaderT r m) where+instance BehaviorWriter t w m => BehaviorWriter t w (ReaderT r m) where tellBehavior = lift . tellBehavior
src/Reflex/FastWeak.hs view
@@ -151,6 +151,16 @@ -- | Create a 'FastWeakTicket' directly from a value, creating a 'FastWeak' in the process -- which can be obtained with 'getFastWeakTicketValue'.+--+-- This function is marked NOINLINE so it is opaque to GHC.+-- If we do not do this, then GHC will sometimes fuse the constructor away+-- so any weak references that are attached to the ticket will have their+-- finalizer run. Using the opaque constructor, GHC does not see the+-- constructor application, so it behaves like an IORef and cannot be fused away.+--+-- The result is also evaluated to WHNF, since forcing a thunk invalidates+-- the weak pointer to it in some cases.+{-# NOINLINE mkFastWeakTicket #-} mkFastWeakTicket :: a -> IO (FastWeakTicket a) -- I think it's fine if this is lazy - it'll retain the 'a', but so would the output; we just need to make sure it's forced before we start relying on the -- associated FastWeak to actually be weak
src/Reflex/PerformEvent/Class.hs view
@@ -22,6 +22,7 @@ import Reflex.TriggerEvent.Class import Control.Monad.Reader+import Control.Monad.Trans.Maybe (MaybeT (..)) -- | 'PerformEvent' represents actions that can trigger other actions based on -- 'Event's.@@ -61,3 +62,8 @@ performEvent e = do r <- ask lift $ performEvent $ flip runReaderT r <$> e++instance PerformEvent t m => PerformEvent t (MaybeT m) where+ type Performable (MaybeT m) = MaybeT (Performable m)+ performEvent_ = lift . performEvent_ . fmapCheap (void . runMaybeT)+ performEvent = lift . fmap (fmapMaybe id) . performEvent . fmapCheap runMaybeT
src/Reflex/Profiled.hs view
@@ -26,6 +26,7 @@ import Control.Monad.Reader import Control.Monad.Ref import Control.Monad.State.Strict (StateT, execStateT, modify)+import Data.Bifunctor import Data.Coerce import Data.Dependent.Map (DMap, GCompare) import Data.FastMutableIntMap@@ -42,12 +43,20 @@ import GHC.Foreign import GHC.IO.Encoding import GHC.Stack+import Reflex.Adjustable.Class+import Reflex.BehaviorWriter.Class import Reflex.Class+import Reflex.DynamicWriter.Class+import Reflex.EventWriter.Class import Reflex.Host.Class+import Reflex.NotReady.Class import Reflex.PerformEvent.Class+import Reflex.PostBuild.Class+import Reflex.Query.Class+import Reflex.Requester.Class+import Reflex.TriggerEvent.Class import System.IO.Unsafe-import Unsafe.Coerce data ProfiledTimeline t @@ -178,6 +187,16 @@ instance MonadSample t m => MonadSample (ProfiledTimeline t) (ProfiledM m) where sample (Behavior_Profiled b) = ProfiledM $ sample b +instance Adjustable t m => Adjustable (ProfiledTimeline t) (ProfiledM m) where+ runWithReplace a0 a' = (fmap . fmap) coerce . lift $+ runWithReplace (coerce a0) (coerce $ coerce <$> a')+ traverseIntMapWithKeyWithAdjust f dm0 dm' = (fmap . fmap) coerce . lift $+ traverseIntMapWithKeyWithAdjust (\k v -> coerce $ f k v) dm0 (coerce dm')+ traverseDMapWithKeyWithAdjust f dm0 dm' = (fmap . fmap) coerce . lift $+ traverseDMapWithKeyWithAdjust (\k v -> coerce $ f k v) dm0 (coerce dm')+ traverseDMapWithKeyWithAdjustWithMove f dm0 dm' = (fmap . fmap) coerce . lift $+ traverseDMapWithKeyWithAdjustWithMove (\k v -> coerce $ f k v) dm0 (coerce dm')+ instance MonadTrans ProfiledM where lift = ProfiledM @@ -188,6 +207,39 @@ type Performable (ProfiledM m) = Performable m performEvent_ = lift . performEvent_ . coerce performEvent = lift . fmap coerce . performEvent . coerce++instance TriggerEvent t m => TriggerEvent (ProfiledTimeline t) (ProfiledM m) where+ newTriggerEvent = first coerce <$> lift newTriggerEvent+ newTriggerEventWithOnComplete = first coerce <$> lift newTriggerEventWithOnComplete+ newEventWithLazyTriggerWithOnComplete f = coerce <$> lift (newEventWithLazyTriggerWithOnComplete f)++instance PostBuild t m => PostBuild (ProfiledTimeline t) (ProfiledM m) where+ getPostBuild = coerce <$> lift getPostBuild++instance NotReady t m => NotReady (ProfiledTimeline t) (ProfiledM m) where+ notReady = lift notReady+ notReadyUntil = lift . notReadyUntil . coerce++instance BehaviorWriter t w m => BehaviorWriter (ProfiledTimeline t) w (ProfiledM m) where+ tellBehavior = lift . tellBehavior . coerce++instance DynamicWriter t w m => DynamicWriter (ProfiledTimeline t) w (ProfiledM m) where+ tellDyn = lift . tellDyn . coerce++instance EventWriter t w m => EventWriter (ProfiledTimeline t) w (ProfiledM m) where+ tellEvent = lift . tellEvent . coerce++instance MonadQuery t q m => MonadQuery (ProfiledTimeline t) q (ProfiledM m) where+ tellQueryIncremental = lift . tellQueryIncremental . coerce+ askQueryResult = coerce <$> lift askQueryResult+ queryIncremental = fmap coerce . lift . queryIncremental . coerce++instance Requester t m => Requester (ProfiledTimeline t) (ProfiledM m) where+ type Request (ProfiledM m) = Request m+ type Response (ProfiledM m) = Response m++ requesting = fmap coerce . lift . requesting . coerce+ requesting_ = lift . requesting_ . coerce instance MonadRef m => MonadRef (ProfiledM m) where type Ref (ProfiledM m) = Ref m
src/Reflex/Query/Class.hs view
@@ -125,7 +125,7 @@ instance Additive SelectedCount --- | The Semigroup/Monoid/Group instances for a Query containing 'SelectedCount's should use+-- | The Semigroup\/Monoid\/Group instances for a Query containing 'SelectedCount's should use -- this function which returns Nothing if the result is 0. This allows the pruning of leaves -- of the 'Query' that are no longer wanted. combineSelectedCounts :: SelectedCount -> SelectedCount -> Maybe SelectedCount@@ -133,12 +133,12 @@ -- | A class that allows sending of 'Query's and retrieval of 'QueryResult's. See 'queryDyn' for a commonly -- used interface.-class (Group q, Additive q, Query q) => MonadQuery t q m | m -> q t where+class (Group q, Additive q, Query q, Monad m) => MonadQuery t q m | m -> q t where tellQueryIncremental :: Incremental t (AdditivePatch q) -> m () askQueryResult :: m (Dynamic t (QueryResult q)) queryIncremental :: Incremental t (AdditivePatch q) -> m (Dynamic t (QueryResult q)) -instance (Monad m, MonadQuery t q m) => MonadQuery t q (ReaderT r m) where+instance MonadQuery t q m => MonadQuery t q (ReaderT r m) where tellQueryIncremental = lift . tellQueryIncremental askQueryResult = lift askQueryResult queryIncremental = lift . queryIncremental@@ -148,11 +148,11 @@ tellQueryDyn d = tellQueryIncremental $ unsafeBuildIncremental (sample (current d)) $ attachWith (\old new -> AdditivePatch $ new ~~ old) (current d) (updated d) -- | Retrieve 'Dynamic'ally updating 'QueryResult's for a 'Dynamic'ally updating 'Query'.-queryDyn :: (Reflex t, Monad m, MonadQuery t q m) => Dynamic t q -> m (Dynamic t (QueryResult q))+queryDyn :: (Reflex t, MonadQuery t q m) => Dynamic t q -> m (Dynamic t (QueryResult q)) queryDyn q = do tellQueryDyn q zipDynWith crop q <$> askQueryResult -- | Use a query morphism to operate on a smaller version of a query.-subQuery :: (Reflex t, MonadQuery t q2 m, Monad m) => QueryMorphism q1 q2 -> Dynamic t q1 -> m (Dynamic t (QueryResult q1))+subQuery :: (Reflex t, MonadQuery t q2 m) => QueryMorphism q1 q2 -> Dynamic t q1 -> m (Dynamic t (QueryResult q1)) subQuery (QueryMorphism f g) x = fmap g <$> queryDyn (fmap f x)
src/Reflex/Spider/Internal.hs view
@@ -450,16 +450,6 @@ , subscriberRecalculateHeight :: !(Height -> IO ()) } ---TODO: Move this comment to WeakBag--- These function are constructor functions that are marked NOINLINE so they are--- opaque to GHC. If we do not do this, then GHC will sometimes fuse the constructor away--- so any weak references that are attached to the constructors will have their--- finalizer run. Using the opaque constructor, does not see the--- constructor application, so it behaves like an IORef and cannot be fused away.------ The result is also evaluated to WHNF, since forcing a thunk invalidates--- the weak pointer to it in some cases.- newSubscriberHold :: (HasSpiderTimeline x, Patch p) => Hold x p -> IO (Subscriber x p) newSubscriberHold h = return $ Subscriber { subscriberPropagate = {-# SCC "traverseHold" #-} propagateSubscriberHold h
src/Reflex/TriggerEvent/Class.hs view
@@ -12,6 +12,7 @@ import Control.Monad.Reader import Control.Monad.State import qualified Control.Monad.State.Strict as Strict+import Control.Monad.Trans.Maybe (MaybeT) --TODO: Shouldn't have IO hard-coded -- | 'TriggerEvent' represents actions that can create 'Event's that can be@@ -44,6 +45,11 @@ newEventWithLazyTriggerWithOnComplete = lift . newEventWithLazyTriggerWithOnComplete instance TriggerEvent t m => TriggerEvent t (Strict.StateT s m) where+ newTriggerEvent = lift newTriggerEvent+ newTriggerEventWithOnComplete = lift newTriggerEventWithOnComplete+ newEventWithLazyTriggerWithOnComplete = lift . newEventWithLazyTriggerWithOnComplete++instance TriggerEvent t m => TriggerEvent t (MaybeT m) where newTriggerEvent = lift newTriggerEvent newTriggerEventWithOnComplete = lift newTriggerEventWithOnComplete newEventWithLazyTriggerWithOnComplete = lift . newEventWithLazyTriggerWithOnComplete