reflex 0.6.2.1 → 0.6.2.3
raw patch · 33 files changed
+307/−151 lines, 33 filesdep +semialigndep +these-lensdep −semigroupsdep −transformers-compatdep ~comonaddep ~constraints-extrasdep ~containers
Dependencies added: semialign, these-lens
Dependencies removed: semigroups, transformers-compat
Dependency ranges changed: comonad, constraints-extras, containers, criterion, deepseq, hlint, monoidal-containers, primitive, profunctors, these, transformers, witherable
Files
- ChangeLog.md +20/−3
- reflex.cabal +62/−32
- src/Control/Monad/ReaderIO.hs +60/−0
- src/Data/AppendMap.hs +2/−0
- src/Data/Functor/Misc.hs +0/−1
- src/Reflex/Adjustable/Class.hs +0/−1
- src/Reflex/BehaviorWriter/Class.hs +0/−1
- src/Reflex/Class.hs +28/−15
- src/Reflex/Collection.hs +4/−0
- src/Reflex/Dynamic/TH.hs +1/−1
- src/Reflex/DynamicWriter/Class.hs +0/−1
- src/Reflex/EventWriter/Base.hs +1/−1
- src/Reflex/EventWriter/Class.hs +0/−1
- src/Reflex/Host/Class.hs +0/−1
- src/Reflex/NotReady/Class.hs +0/−1
- src/Reflex/Patch/IntMap.hs +0/−8
- src/Reflex/Patch/Map.hs +0/−8
- src/Reflex/PerformEvent/Base.hs +1/−1
- src/Reflex/PerformEvent/Class.hs +0/−1
- src/Reflex/PostBuild/Class.hs +0/−1
- src/Reflex/Profiled.hs +14/−10
- src/Reflex/Pure.hs +3/−6
- src/Reflex/Query/Base.hs +0/−1
- src/Reflex/Query/Class.hs +0/−1
- src/Reflex/Requester/Class.hs +0/−1
- src/Reflex/Spider/Internal.hs +78/−49
- src/Reflex/TriggerEvent/Class.hs +0/−1
- test/EventWriterT.hs +6/−4
- test/QueryT.hs +4/−0
- test/Reflex/Bench/Focused.hs +12/−0
- test/Reflex/Test/CrossImpl.hs +5/−0
- test/RequesterT.hs +5/−0
- test/hlint.hs +1/−0
ChangeLog.md view
@@ -1,16 +1,33 @@ # Revision history for reflex -## Unreleased+## 0.6.2.3 +* Add an upper-bound to witherable++## 0.6.2.2++* Support these >= 1. Add `split-these` flag to control whether to use new these/semialign combination or not.+* Update version bounds to fix some CI failures+* Add travis CI configuration++## 0.6.2.1+ * Generalize `fan` to `fanG` to take a `DMap` with non-`Identity`- values.+ functor:+ * `fan` to `fanG`+ * `EventSelectorG` for `fanG` result selector. +* Reduce the amount of unsafeCoerce in coercing newtypes under Event/Dynamic/Behavior.+ * Add fused ReaderIO for the purpose of coercion (ReaderT's third argument has nominal role preventing automated coerce)+ * Add incrementalCoercion/coerceIncremental to go with dynamicCoercion/coerceDynamic+ * Generalize merging functions: `merge` to `mergeG`, `mergeIncremental` to `mergeIncrementalG`, - `distributeDMapOverDynPure` to `distributeDMapOverDynPureG`, `mergeIncrementalWithMove` to `mergeIncrementalWithMoveG`. +* Generalize distribute function:+ `distributeDMapOverDynPure` to `distributeDMapOverDynPureG`, ## 0.6.2.0
reflex.cabal view
@@ -1,5 +1,5 @@ Name: reflex-Version: 0.6.2.1+Version: 0.6.2.3 Synopsis: Higher-order Functional Reactive Programming Description: Reflex is a high-performance, deterministic, higher-order Functional Reactive Programming system License: BSD3@@ -17,6 +17,10 @@ Quickref.md ChangeLog.md +tested-with:+ GHC ==8.0.2 || ==8.2.2 || ==8.4.4 || ==8.6.5,+ GHCJS ==8.4+ flag use-reflex-optimizer description: Use the GHC plugin Reflex.Optimizer on some of the modules in the package. This is still experimental. default: False@@ -37,40 +41,51 @@ default: False manual: True +flag split-these+ description: Use split these/semialign packages+ manual: False+ default: True+ library hs-source-dirs: src build-depends: MemoTrie == 0.6.*, base >= 4.9 && < 4.13, bifunctors >= 5.2 && < 5.6,- comonad,- constraints-extras >= 0.2,- containers >= 0.5 && < 0.7,+ comonad >= 5.0.4 && < 5.1,+ constraints-extras >= 0.3 && < 0.4,+ containers >= 0.6 && < 0.7, data-default >= 0.5 && < 0.8, dependent-map >= 0.3 && < 0.4, exception-transformers == 0.4.*,- profunctors,+ profunctors >= 5.3 && < 5.5, lens >= 4.7 && < 5, monad-control >= 1.0.1 && < 1.1,- monoidal-containers >= 0.4 && < 0.6, mtl >= 2.1 && < 2.3, prim-uniq >= 0.1.0.1 && < 0.2,- primitive >= 0.5 && < 0.7,+ primitive >= 0.5 && < 0.8,+ profunctors, random == 1.1.*, ref-tf == 0.4.*, reflection == 2.1.*, semigroupoids >= 4.0 && < 6,- semigroups >= 0.16 && < 0.19, stm >= 2.4 && < 2.6, syb >= 0.5 && < 0.8,- these >= 0.4 && < 0.9, time >= 1.4 && < 1.9,- transformers >= 0.2,- transformers-compat >= 0.3,+ transformers >= 0.5.6.0 && < 0.6, unbounded-delays >= 0.1.0.0 && < 0.2,- witherable >= 0.2 && < 0.4+ witherable >= 0.3 && < 0.3.2 + if flag(split-these)+ build-depends: these >= 1 && <1.1,+ semialign >=1 && <1.1,+ monoidal-containers >= 0.5.0.1 && < 0.6+ else+ build-depends: these >= 0.4 && <0.9,+ monoidal-containers == 0.5.0.0+ exposed-modules:+ Control.Monad.ReaderIO Data.AppendMap, Data.FastMutableIntMap, Data.FastWeakBag,@@ -144,7 +159,7 @@ other-extensions: TemplateHaskell else build-depends:- dependent-sum == 0.6.*+ dependent-sum >= 0.6 && < 0.7 if flag(fast-weak) && impl(ghcjs) cpp-options: -DGHCJS_FAST_WEAK@@ -161,14 +176,14 @@ base, bifunctors, containers,- deepseq >= 1.3 && < 1.5,+ deepseq, dependent-map, dependent-sum, mtl, ref-tf, reflex, split,- transformers >= 0.3+ transformers other-modules: Reflex.Bench.Focused Reflex.Plan.Pure@@ -187,7 +202,7 @@ containers, dependent-map, dependent-sum,- deepseq >= 1.3 && < 1.5,+ deepseq, mtl, transformers, ref-tf,@@ -206,7 +221,7 @@ , directory , filepath , filemanip- , hlint+ , hlint < 2.1 || >= 2.2.2 if impl(ghcjs) buildable: False @@ -216,7 +231,7 @@ hs-source-dirs: test build-depends: base , containers- , deepseq >= 1.3 && < 1.5+ , deepseq , dependent-map , dependent-sum , lens@@ -225,6 +240,10 @@ , transformers , reflex , ref-tf++ if flag(split-these)+ build-depends: these-lens+ other-modules: Reflex.Test Reflex.TestPlan@@ -232,13 +251,14 @@ Reflex.Plan.Pure Test.Run + test-suite RequesterT type: exitcode-stdio-1.0 main-is: RequesterT.hs hs-source-dirs: test build-depends: base , containers- , deepseq >= 1.3 && < 1.5+ , deepseq , dependent-sum , dependent-map , lens@@ -247,9 +267,14 @@ , transformers , reflex , ref-tf++ if flag(split-these)+ build-depends: these-lens+ other-modules: Reflex.TestPlan Reflex.Plan.Pure+ Test.Run test-suite QueryT type: exitcode-stdio-1.0@@ -259,15 +284,18 @@ , containers , dependent-map , dependent-sum- , deepseq >= 1.3 && < 1.5+ , deepseq , lens , monoidal-containers , mtl , ref-tf , reflex- , semigroups , these , transformers++ if flag(split-these)+ build-depends: semialign, these-lens+ other-modules: Test.Run Reflex.TestPlan@@ -282,14 +310,16 @@ , containers , dependent-sum , dependent-map- , deepseq >= 1.3 && < 1.5+ , deepseq , mtl , these , transformers , reflex , ref-tf- if impl(ghc < 8)- build-depends: semigroups++ if flag(split-these)+ build-depends: semialign+ other-modules: Reflex.Plan.Pure Reflex.Plan.Reflex@@ -302,7 +332,7 @@ hs-source-dirs: test build-depends: base , containers- , deepseq >= 1.3 && < 1.5+ , deepseq , dependent-sum , mtl , reflex@@ -321,8 +351,8 @@ build-depends: base, containers,- criterion >= 1.1 && < 1.6,- deepseq >= 1.3 && < 1.5,+ criterion,+ deepseq, dependent-map, dependent-sum, ref-tf,@@ -331,7 +361,7 @@ reflex, split, stm,- transformers >= 0.3+ transformers other-modules: Reflex.TestPlan Reflex.Plan.Reflex@@ -345,9 +375,9 @@ ghc-options: -Wall -O2 -rtsopts -threaded build-depends: base,- containers >= 0.5 && < 0.7,- criterion >= 1.1 && < 1.6,- deepseq >= 1.3 && < 1.5,+ containers,+ criterion,+ deepseq, dependent-map, dependent-sum, loch-th,@@ -359,7 +389,7 @@ split, stm, time,- transformers >= 0.3+ transformers other-modules: Reflex.TestPlan Reflex.Plan.Reflex
+ src/Control/Monad/ReaderIO.hs view
@@ -0,0 +1,60 @@+{-# language RoleAnnotations #-}+{-# language MultiParamTypeClasses #-}+{-# language FlexibleInstances #-}+{-# language CPP #-}+module Control.Monad.ReaderIO+ (+ ReaderIO (..)+ )+ where++import Control.Monad.Fix+#if MIN_VERSION_base(4,10,0)+import Control.Applicative+#endif+import Control.Monad+import Control.Monad.Reader.Class+import Control.Monad.IO.Class++-- | An approximate clone of @RIO@ from the @rio@ package, but not based on+-- @ReaderT@. The trouble with @ReaderT@ is that its third type argument has a+-- @nominal@ role, so we can't coerce through it when it's wrapped in some+-- other @data@ type. Ugh.+newtype ReaderIO e a = ReaderIO { runReaderIO :: e -> IO a }+type role ReaderIO representational representational++instance Functor (ReaderIO e) where+ fmap = liftM+ {-# INLINE fmap #-}+ a <$ m = m >> pure a+ {-# INLINE (<$) #-}++instance Applicative (ReaderIO e) where+ pure a = ReaderIO $ \_ -> pure a+ {-# INLINE pure #-}+ (<*>) = ap+ {-# INLINE (<*>) #-}+#if MIN_VERSION_base(4,10,0)+ liftA2 = liftM2+ {-# INLINE liftA2 #-}+#endif + (*>) = (>>)+ {-# INLINE (*>) #-}++instance Monad (ReaderIO e) where+ ReaderIO q >>= f = ReaderIO $ \e -> q e >>= \a -> runReaderIO (f a) e+ {-# INLINE (>>=) #-}++instance MonadFix (ReaderIO e) where+ mfix f = ReaderIO $ \e -> mfix $ \r -> runReaderIO (f r) e+ {-# INLINE mfix #-}++instance MonadIO (ReaderIO e) where+ liftIO m = ReaderIO $ \_ -> m+ {-# INLINE liftIO #-}++instance MonadReader e (ReaderIO e) where+ ask = ReaderIO pure+ {-# INLINE ask #-}+ local f (ReaderIO m) = ReaderIO (m . f)+ {-# INLINE local #-}
src/Data/AppendMap.hs view
@@ -46,8 +46,10 @@ pattern AppendMap :: Map k v -> MonoidalMap k v pattern AppendMap m = MonoidalMap m +#if !MIN_VERSION_witherable(0,3,2) instance W.Filterable (MonoidalMap k) where mapMaybe = mapMaybe+#endif -- | Deletes a key, returning 'Nothing' if the result is empty. nonEmptyDelete :: Ord k => k -> MonoidalMap k a -> Maybe (MonoidalMap k a)
src/Data/Functor/Misc.hs view
@@ -4,7 +4,6 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-}-{-# LANGUAGE KindSignatures #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE PatternSynonyms #-}
src/Reflex/Adjustable/Class.hs view
@@ -3,7 +3,6 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE LambdaCase #-}-{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-}
src/Reflex/BehaviorWriter/Class.hs view
@@ -5,7 +5,6 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE UndecidableInstances #-} #ifdef USE_REFLEX_OPTIMIZER {-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
src/Reflex/Class.hs view
@@ -7,7 +7,6 @@ {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-}-{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NoMonomorphismRestriction #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE RankNTypes #-}@@ -37,6 +36,7 @@ , coerceBehavior , coerceEvent , coerceDynamic+ , coerceIncremental , MonadSample (..) , MonadHold (..) -- ** 'fan' related types@@ -173,6 +173,14 @@ , slowHeadE ) where +#if defined(MIN_VERSION_semialign)+import Prelude hiding (zip, zipWith)++#if MIN_VERSION_these(0,8,0)+import Data.These.Combinators (justThese)+#endif+#endif+ import Control.Applicative import Control.Monad.Identity import Control.Monad.Reader@@ -312,6 +320,10 @@ -- | Construct a 'Coercion' for a 'Dynamic' given an 'Coercion' for its -- occurrence type dynamicCoercion :: Coercion a b -> Coercion (Dynamic t a) (Dynamic t b)+ -- | Construct a 'Coercion' for an 'Incremental' given 'Coercion's for its+ -- patch target and patch types.+ incrementalCoercion+ :: Coercion (PatchTarget a) (PatchTarget b) -> Coercion a b -> Coercion (Incremental t a) (Incremental t b) mergeIntIncremental :: Incremental t (PatchIntMap (Event t a)) -> Event t (IntMap a) fanInt :: Event t (IntMap a) -> EventSelectorInt t a @@ -345,6 +357,12 @@ coerceDynamic :: (Reflex t, Coercible a b) => Dynamic t a -> Dynamic t b coerceDynamic = coerceWith $ dynamicCoercion Coercion +-- | Coerce an 'Incremental' between representationally-equivalent value types+coerceIncremental+ :: (Reflex t, Coercible a b, Coercible (PatchTarget a) (PatchTarget b))+ => Incremental t a -> Incremental t b+coerceIncremental = coerceWith $ incrementalCoercion Coercion Coercion+ -- | Construct a 'Dynamic' from a 'Behavior' and an 'Event'. The 'Behavior' -- __must__ change when and only when the 'Event' fires, such that the -- 'Behavior''s value is always equal to the most recent firing of the 'Event';@@ -669,11 +687,7 @@ instance (Reflex t, Semigroup a) => Semigroup (Behavior t a) where a <> b = pull $ liftM2 (<>) (sample a) (sample b) sconcat = pull . fmap sconcat . mapM sample-#if MIN_VERSION_semigroups(0,17,0) stimes n = fmap $ stimes n-#else- times1p n = fmap $ times1p n-#endif -- | Alias for 'mapMaybe' fmapMaybe :: Filterable f => (a -> Maybe b) -> f a -> f b@@ -700,10 +714,13 @@ instance Reflex t => Alt (Event t) where ev1 <!> ev2 = leftmost [ev1, ev2] --- | 'Event' intersection (convenient interface to 'coincidence').+-- | 'Event' intersection. Only occurs when both events are co-incident. instance Reflex t => Apply (Event t) where- evf <.> evx = coincidence (fmap (<$> evx) evf)+ evf <.> evx = mapMaybe f (align evf evx) where+ f (These g a) = Just (g a)+ f _ = Nothing + -- | 'Event' intersection (convenient interface to 'coincidence'). instance Reflex t => Bind (Event t) where evx >>- f = coincidence (f <$> evx)@@ -871,11 +888,7 @@ instance (Semigroup a, Reflex t) => Semigroup (Event t a) where (<>) = alignWith (mergeThese (<>)) sconcat = fmap sconcat . mergeList . toList-#if MIN_VERSION_semigroups(0,17,0) stimes n = fmap $ stimes n-#else- times1p n = fmap $ times1p n-#endif instance (Semigroup a, Reflex t) => Monoid (Event t a) where mempty = never@@ -1064,7 +1077,11 @@ #endif align = alignEventWithMaybe Just +#if defined(MIN_VERSION_semialign)+ zip x y = mapMaybe justThese $ align x y+#endif + -- | Create a new 'Event' that only occurs if the supplied 'Event' occurs and -- the 'Behavior' is true at the time of occurrence. gate :: Reflex t => Behavior t Bool -> Event t a -> Event t a@@ -1104,11 +1121,7 @@ instance (Reflex t, Semigroup a) => Semigroup (Dynamic t a) where (<>) = zipDynWith (<>)-#if MIN_VERSION_semigroups(0,17,0) stimes n = fmap $ stimes n-#else- times1p n = fmap $ times1p n-#endif instance (Reflex t, Monoid a) => Monoid (Dynamic t a) where mconcat = distributeListOverDynWith mconcat
src/Reflex/Collection.hs view
@@ -27,6 +27,10 @@ , simpleList ) where +#if defined(MIN_VERSION_semialign)+import Prelude hiding (zip, zipWith)+#endif+ import Control.Monad.Identity import Data.Align import Data.Functor.Misc
src/Reflex/Dynamic/TH.hs view
@@ -81,7 +81,7 @@ } mkDynExp :: String -> Q Exp-mkDynExp s = case Hs.parseExpWithMode (Hs.defaultParseMode { Hs.extensions = [ Hs.EnableExtension Hs.TemplateHaskell ] }) s of+mkDynExp s = case Hs.parseExpWithMode Hs.defaultParseMode { Hs.extensions = [ Hs.EnableExtension Hs.TemplateHaskell ] } s of Hs.ParseFailed (Hs.SrcLoc _ l c) err -> fail $ "mkDyn:" <> show l <> ":" <> show c <> ": " <> err Hs.ParseOk e -> qDynPure $ return $ everywhere (id `extT` reinstateUnqDyn) $ Hs.toExp $ everywhere (id `extT` antiE) e where TH.Name (TH.OccName occName) (TH.NameG _ _ (TH.ModName modName)) = 'unqMarker
src/Reflex/DynamicWriter/Class.hs view
@@ -3,7 +3,6 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE UndecidableInstances #-} #ifdef USE_REFLEX_OPTIMIZER {-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
src/Reflex/EventWriter/Base.hs view
@@ -52,7 +52,7 @@ import Data.Semigroup import Data.Some (Some) import Data.Tuple-import Data.Type.Equality hiding (apply)+import Data.Type.Equality import Unsafe.Coerce
src/Reflex/EventWriter/Class.hs view
@@ -2,7 +2,6 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE UndecidableInstances #-} #ifdef USE_REFLEX_OPTIMIZER {-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
src/Reflex/Host/Class.hs view
@@ -4,7 +4,6 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE GADTs #-}-{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE RoleAnnotations #-} {-# LANGUAGE ScopedTypeVariables #-}
src/Reflex/NotReady/Class.hs view
@@ -3,7 +3,6 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} #ifdef USE_REFLEX_OPTIMIZER
src/Reflex/Patch/IntMap.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveFoldable #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DeriveTraversable #-}@@ -33,14 +32,7 @@ instance Semigroup (PatchIntMap v) where PatchIntMap a <> PatchIntMap b = PatchIntMap $ a `mappend` b --TODO: Add a semigroup instance for Map -- PatchMap is idempotent, so stimes n is id for every n-#if MIN_VERSION_semigroups(0,17,0) stimes = stimesIdempotentMonoid-#else- times1p n x = case compare n 0 of- LT -> error "stimesIdempotentMonoid: negative multiplier"- EQ -> mempty- GT -> x-#endif -- | Map a function @Int -> a -> b@ over all @a@s in the given @'PatchIntMap' a@ -- (that is, all inserts/updates), producing a @PatchIntMap b@.
src/Reflex/Patch/Map.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE CPP #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE TypeFamilies #-} -- | 'Patch'es on 'Map' that consist only of insertions (including overwrites)@@ -35,14 +34,7 @@ instance Ord k => Semigroup (PatchMap k v) where PatchMap a <> PatchMap b = PatchMap $ a `mappend` b --TODO: Add a semigroup instance for Map -- PatchMap is idempotent, so stimes n is id for every n-#if MIN_VERSION_semigroups(0,17,0) stimes = stimesIdempotentMonoid-#else- times1p n x = case compare n 0 of- LT -> error "stimesIdempotentMonoid: negative multiplier"- EQ -> mempty- GT -> x-#endif -- | The empty 'PatchMap' contains no insertions or deletions instance Ord k => Monoid (PatchMap k v) where
src/Reflex/PerformEvent/Base.hs view
@@ -141,7 +141,7 @@ case mToPerform of Nothing -> return [result'] Just toPerform -> do- responses <- runHostFrame $ traverseRequesterData (\v -> Identity <$> v) toPerform+ responses <- runHostFrame $ traverseRequesterData (Identity <$>) toPerform mrt <- readRef responseTrigger let followupEventTriggers = case mrt of Just rt -> [rt :=> Identity responses]
src/Reflex/PerformEvent/Class.hs view
@@ -5,7 +5,6 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-}
src/Reflex/PostBuild/Class.hs view
@@ -4,7 +4,6 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-}
src/Reflex/Profiled.hs view
@@ -9,6 +9,7 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE PolyKinds #-}+{-# LANGUAGE TypeApplications #-} {-# LANGUAGE RankNTypes #-} -- | -- Module:@@ -79,9 +80,9 @@ go (cc : l) parent toCostCentreTree :: Ptr CostCentreStack -> Int -> IO CostCentreTree-toCostCentreTree ccs n = do- ccList <- getCostCentreStack ccs- return $ foldr (\cc child -> CostCentreTree 0 n $ Map.singleton cc child) (CostCentreTree n n mempty) ccList+toCostCentreTree ccs n =+ foldr (\cc child -> CostCentreTree 0 n $ Map.singleton cc child) (CostCentreTree n n mempty)+ <$> getCostCentreStack ccs getCostCentreTree :: IO CostCentreTree getCostCentreTree = do@@ -151,13 +152,16 @@ currentIncremental (Incremental_Profiled i) = coerce $ currentIncremental i updatedIncremental (Incremental_Profiled i) = coerce $ profileEvent $ updatedIncremental i incrementalToDynamic (Incremental_Profiled i) = coerce $ incrementalToDynamic i- behaviorCoercion (c :: Coercion a b) = case behaviorCoercion c :: Coercion (Behavior t a) (Behavior t b) of- Coercion -> unsafeCoerce (Coercion :: Coercion (Behavior (ProfiledTimeline t) a) (Behavior (ProfiledTimeline t) a)) --TODO: Figure out how to make this typecheck without the unsafeCoerce- eventCoercion (c :: Coercion a b) = case eventCoercion c :: Coercion (Event t a) (Event t b) of- Coercion -> unsafeCoerce (Coercion :: Coercion (Event (ProfiledTimeline t) a) (Event (ProfiledTimeline t) a)) --TODO: Figure out how to make this typecheck without the unsafeCoerce- dynamicCoercion (c :: Coercion a b) = case dynamicCoercion c :: Coercion (Dynamic t a) (Dynamic t b) of- Coercion -> unsafeCoerce (Coercion :: Coercion (Dynamic (ProfiledTimeline t) a) (Dynamic (ProfiledTimeline t) a)) --TODO: Figure out how to make this typecheck without the unsafeCoerce- mergeIntIncremental = Event_Profiled . mergeIntIncremental . (unsafeCoerce :: Incremental (ProfiledTimeline t) (PatchIntMap (Event (ProfiledTimeline t) a)) -> Incremental t (PatchIntMap (Event t a)))+ behaviorCoercion c =+ Coercion `trans` behaviorCoercion @t c `trans` Coercion+ eventCoercion c =+ Coercion `trans` eventCoercion @t c `trans` Coercion+ dynamicCoercion c =+ Coercion `trans` dynamicCoercion @t c `trans` Coercion+ incrementalCoercion c d =+ Coercion `trans` incrementalCoercion @t c d `trans` Coercion+ mergeIntIncremental = Event_Profiled . mergeIntIncremental .+ coerceWith (Coercion `trans` incrementalCoercion Coercion Coercion `trans` Coercion) fanInt (Event_Profiled e) = coerce $ fanInt $ profileEvent e deriving instance Functor (Dynamic t) => Functor (Dynamic (ProfiledTimeline t))
src/Reflex/Pure.hs view
@@ -31,14 +31,9 @@ , Incremental (..) ) where -#if !MIN_VERSION_base(4,8,0)-import Control.Applicative-#endif- import Control.Monad import Data.Dependent.Map (DMap, GCompare) import qualified Data.Dependent.Map as DMap-import Data.Functor.Identity import Data.IntMap (IntMap) import qualified Data.IntMap as IntMap import Data.Maybe@@ -93,7 +88,8 @@ then Nothing else Just currentOccurrences - -- fanG :: GCompare k => Event (Pure t) (DMap k v) -> EventSelectorG (Pure t) k v+-- The instance signature doeesn't compile, leave commented for documentation+-- fanG :: GCompare k => Event (Pure t) (DMap k v) -> EventSelectorG (Pure t) k v fanG e = EventSelectorG $ \k -> Event $ \t -> unEvent e t >>= DMap.lookup k switch :: Behavior (Pure t) (Event (Pure t) a) -> Event (Pure t) a@@ -133,6 +129,7 @@ behaviorCoercion Coercion = Coercion eventCoercion Coercion = Coercion dynamicCoercion Coercion = Coercion+ incrementalCoercion Coercion Coercion = Coercion fanInt e = EventSelectorInt $ \k -> Event $ \t -> unEvent e t >>= IntMap.lookup k
src/Reflex/Query/Base.hs view
@@ -1,7 +1,6 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE InstanceSigs #-}-{-# LANGUAGE KindSignatures #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RankNTypes #-}
src/Reflex/Query/Class.hs view
@@ -3,7 +3,6 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} -- |
src/Reflex/Requester/Class.hs view
@@ -6,7 +6,6 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RecursiveDo #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-}
src/Reflex/Spider/Internal.hs view
@@ -9,7 +9,6 @@ {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE LambdaCase #-}-{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE MultiWayIf #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE RoleAnnotations #-}@@ -18,6 +17,8 @@ {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE PolyKinds #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE InstanceSigs #-} #ifdef USE_REFLEX_OPTIMIZER@@ -37,7 +38,10 @@ import Control.Monad.Exception import Control.Monad.Identity hiding (forM, forM_, mapM, mapM_) import Control.Monad.Primitive-import Control.Monad.Reader hiding (forM, forM_, mapM, mapM_)+--import Control.Monad.Reader hiding (forM, forM_, mapM, mapM_)+import Control.Monad.Reader.Class+import Control.Monad.IO.Class+import Control.Monad.ReaderIO import Control.Monad.Ref import Data.Align import Data.Coerce@@ -68,6 +72,12 @@ import System.Mem.Weak import Unsafe.Coerce +#if defined(MIN_VERSION_semialign)+#if MIN_VERSION_these(0,8,0)+import Data.These.Combinators (justThese)+#endif+#endif+ #ifdef DEBUG_CYCLES import Control.Monad.State hiding (forM, forM_, mapM, mapM_, sequence) import Data.List.NonEmpty (NonEmpty (..), nonEmpty)@@ -545,6 +555,11 @@ toAny :: a -> Any toAny = unsafeCoerce +-- Why do we use Any here, instead of just giving eventSubscribedRetained an+-- existential type? Sadly, GHC does not currently know how to unbox types+-- with existentially quantified fields. So instead we just coerce values+-- to type Any on the way in. Since we never coerce them back, this is+-- perfectly safe. data EventSubscribed x = EventSubscribed { eventSubscribedHeightRef :: {-# UNPACK #-} !(IORef Height) , eventSubscribedRetained :: {-# NOUNPACK #-} !Any@@ -668,7 +683,7 @@ wi <- liftIO $ mkWeakPtrWithDebug i "InvalidatorPull" parentsRef <- liftIO $ newIORef [] holdInits <- askBehaviorHoldInits- a <- liftIO $ runReaderT (unBehaviorM $ pullCompute p) (Just (wi, parentsRef), holdInits)+ a <- liftIO $ runReaderIO (unBehaviorM $ pullCompute p) (Just (wi, parentsRef), holdInits) invsRef <- liftIO . newIORef . maybeToList =<< askInvalidator parents <- liftIO $ readIORef parentsRef let subscribed = PullSubscribed@@ -703,42 +718,46 @@ -- Dynamic -------------------------------------------------------------------------------- -data Dynamic x p = Dynamic- { dynamicCurrent :: !(Behavior x (PatchTarget p))+type DynamicS x p = Dynamic x (PatchTarget p) p++data Dynamic x target p = Dynamic+ { dynamicCurrent :: !(Behavior x target) , dynamicUpdated :: Event x p -- This must be lazy; see the comment on holdEvent --TODO: Would this let us eliminate `Dyn`? } -dynamicHold :: Hold x p -> Dynamic x p+deriving instance (HasSpiderTimeline x) => Functor (Dynamic x target)+++++dynamicHold :: Hold x p -> DynamicS x p dynamicHold !h = Dynamic { dynamicCurrent = behaviorHold h , dynamicUpdated = eventHold h } -dynamicHoldIdentity :: Hold x (Identity a) -> Dynamic x (Identity a)+dynamicHoldIdentity :: Hold x (Identity a) -> DynamicS x (Identity a) dynamicHoldIdentity = dynamicHold -dynamicConst :: PatchTarget p -> Dynamic x p+dynamicConst :: PatchTarget p -> DynamicS x p dynamicConst !a = Dynamic { dynamicCurrent = behaviorConst a , dynamicUpdated = eventNever } -dynamicDyn :: (HasSpiderTimeline x, Patch p) => Dyn x p -> Dynamic x p+dynamicDyn :: (HasSpiderTimeline x, Patch p) => Dyn x p -> DynamicS x p dynamicDyn !d = Dynamic { dynamicCurrent = behaviorDyn d , dynamicUpdated = eventDyn d } -dynamicDynIdentity :: HasSpiderTimeline x => Dyn x (Identity a) -> Dynamic x (Identity a)+dynamicDynIdentity :: HasSpiderTimeline x => Dyn x (Identity a) -> DynamicS x (Identity a) dynamicDynIdentity = dynamicDyn -------------------------------------------------------------------------------- -- Combinators -------------------------------------------------------------------------------- ---TODO: Figure out why certain things are not 'representational', then make them---representational so we can use coerce- --type role Hold representational data Hold x p = Hold { holdValue :: !(IORef (PatchTarget p))@@ -759,20 +778,25 @@ -- | Stores all global data relevant to a particular Spider timeline; only one -- value should exist for each type @x@-data SpiderTimelineEnv x = SpiderTimelineEnv+newtype SpiderTimelineEnv x = STE {unSTE :: SpiderTimelineEnv' x}+-- We implement SpiderTimelineEnv with a newtype wrapper so+-- we can get the coercions we want safely.+type role SpiderTimelineEnv nominal++data SpiderTimelineEnv' x = SpiderTimelineEnv { _spiderTimeline_lock :: {-# UNPACK #-} !(MVar ()) , _spiderTimeline_eventEnv :: {-# UNPACK #-} !(EventEnv x) #ifdef DEBUG , _spiderTimeline_depth :: {-# UNPACK #-} !(IORef Int) #endif }-type role SpiderTimelineEnv nominal+type role SpiderTimelineEnv' phantom instance Eq (SpiderTimelineEnv x) where _ == _ = True -- Since only one exists of each type instance GEq SpiderTimelineEnv where- a `geq` b = if _spiderTimeline_lock a == _spiderTimeline_lock b+ a `geq` b = if _spiderTimeline_lock (unSTE a) == _spiderTimeline_lock (unSTE b) then Just $ unsafeCoerce Refl -- This unsafeCoerce is safe because the same SpiderTimelineEnv can't have two different 'x' arguments else Nothing @@ -795,7 +819,7 @@ runEventM = unEventM asksEventEnv :: forall x a. HasSpiderTimeline x => (EventEnv x -> a) -> EventM x a-asksEventEnv f = return $ f $ _spiderTimeline_eventEnv (spiderTimeline :: SpiderTimelineEnv x)+asksEventEnv f = return $ f $ _spiderTimeline_eventEnv (unSTE (spiderTimeline :: SpiderTimelineEnv x)) class MonadIO m => Defer a m where getDeferralQueue :: m (IORef [a])@@ -933,9 +957,9 @@ type BehaviorEnv x = (Maybe (Weak (Invalidator x), IORef [SomeBehaviorSubscribed x]), IORef [SomeHoldInit x]) ---type role BehaviorM representational -- BehaviorM can sample behaviors-newtype BehaviorM x a = BehaviorM { unBehaviorM :: ReaderT (BehaviorEnv x) IO a } deriving (Functor, Applicative, MonadIO, MonadFix)+newtype BehaviorM x a = BehaviorM { unBehaviorM :: ReaderIO (BehaviorEnv x) a }+ deriving (Functor, Applicative, MonadIO, MonadFix, MonadReader (BehaviorEnv x)) instance Monad (BehaviorM x) where {-# INLINE (>>=) #-}@@ -1139,17 +1163,21 @@ align ea eb = mapMaybe dmapToThese $ mergeG coerce $ dynamicConst $ DMap.fromDistinctAscList [LeftTag :=> ea, RightTag :=> eb] +#if defined(MIN_VERSION_semialign)+ zip x y = mapMaybe justThese $ align x y+#endif+ data DynType x p = UnsafeDyn !(BehaviorM x (PatchTarget p), Event x p) | BuildDyn !(EventM x (PatchTarget p), Event x p) | HoldDyn !(Hold x p) newtype Dyn (x :: Type) p = Dyn { unDyn :: IORef (DynType x p) } -newMapDyn :: HasSpiderTimeline x => (a -> b) -> Dynamic x (Identity a) -> Dynamic x (Identity b)+newMapDyn :: HasSpiderTimeline x => (a -> b) -> DynamicS x (Identity a) -> DynamicS x (Identity b) newMapDyn f d = dynamicDynIdentity $ unsafeBuildDynamic (fmap f $ readBehaviorTracked $ dynamicCurrent d) (Identity . f . runIdentity <$> dynamicUpdated d) --TODO: Avoid the duplication between this and R.zipDynWith-zipDynWith :: HasSpiderTimeline x => (a -> b -> c) -> Dynamic x (Identity a) -> Dynamic x (Identity b) -> Dynamic x (Identity c)+zipDynWith :: HasSpiderTimeline x => (a -> b -> c) -> DynamicS x (Identity a) -> DynamicS x (Identity b) -> DynamicS x (Identity c) zipDynWith f da db = let eab = align (dynamicUpdated da) (dynamicUpdated db) ec = flip push eab $ \o -> do@@ -1225,7 +1253,7 @@ run roots after = do tracePropagate (Proxy :: Proxy x) $ "Running an event frame with " <> show (length roots) <> " events" let t = spiderTimeline :: SpiderTimelineEnv x- result <- SpiderHost $ withMVar (_spiderTimeline_lock t) $ \_ -> unSpiderHost $ runFrame $ do+ result <- SpiderHost $ withMVar (_spiderTimeline_lock (unSTE t)) $ \_ -> unSpiderHost $ runFrame $ do rootsToPropagate <- forM roots $ \r@(RootTrigger (_, occRef, k) :=> a) -> do occBefore <- liftIO $ do occBefore <- readIORef occRef@@ -1289,9 +1317,9 @@ withIncreasedDepth :: CanTrace x m => m a -> m a withIncreasedDepth a = do spiderTimeline <- askSpiderTimelineEnv- liftIO $ modifyIORef' (_spiderTimeline_depth spiderTimeline) succ+ liftIO $ modifyIORef' (_spiderTimeline_depth (unSTE spiderTimeline)) succ result <- a- liftIO $ modifyIORef' (_spiderTimeline_depth spiderTimeline) pred+ liftIO $ modifyIORef' (_spiderTimeline_depth (unSTE spiderTimeline)) pred return result #else withIncreasedDepth :: m a -> m a@@ -1318,7 +1346,7 @@ message <- getMessage #ifdef DEBUG spiderTimeline <- askSpiderTimelineEnv- d <- liftIO $ readIORef $ _spiderTimeline_depth spiderTimeline+ d <- liftIO $ readIORef $ _spiderTimeline_depth $ unSTE spiderTimeline #else let d = 0 #endif@@ -1359,25 +1387,25 @@ data SomeResetCoincidence x = forall a. SomeResetCoincidence !(EventSubscription x) !(Maybe (CoincidenceSubscribed x a)) -- The CoincidenceSubscriber will be present only if heights need to be reset runBehaviorM :: BehaviorM x a -> Maybe (Weak (Invalidator x), IORef [SomeBehaviorSubscribed x]) -> IORef [SomeHoldInit x] -> IO a-runBehaviorM a mwi holdInits = runReaderT (unBehaviorM a) (mwi, holdInits)+runBehaviorM a mwi holdInits = runReaderIO (unBehaviorM a) (mwi, holdInits) askInvalidator :: BehaviorM x (Maybe (Weak (Invalidator x))) askInvalidator = do- (!m, _) <- BehaviorM ask+ (!m, _) <- ask case m of Nothing -> return Nothing Just (!wi, _) -> return $ Just wi askParentsRef :: BehaviorM x (Maybe (IORef [SomeBehaviorSubscribed x])) askParentsRef = do- (!m, _) <- BehaviorM ask+ (!m, _) <- ask case m of Nothing -> return Nothing Just (_, !p) -> return $ Just p askBehaviorHoldInits :: BehaviorM x (IORef [SomeHoldInit x]) askBehaviorHoldInits = do- (_, !his) <- BehaviorM ask+ (_, !his) <- ask return his {-# INLINE getDynHold #-}@@ -1701,20 +1729,20 @@ {-# INLINE mergeG #-} mergeG :: forall k q x v. (HasSpiderTimeline x, GCompare k) => (forall a. q a -> Event x (v a))- -> Dynamic x (PatchDMap k q) -> Event x (DMap k v)+ -> DynamicS x (PatchDMap k q) -> Event x (DMap k v) mergeG nt d = cacheEvent (mergeCheap nt d) {-# INLINE mergeWithMove #-} mergeWithMove :: forall k v q x. (HasSpiderTimeline x, GCompare k) => (forall a. q a -> Event x (v a))- -> Dynamic x (PatchDMapWithMove k q) -> Event x (DMap k v)+ -> DynamicS x (PatchDMapWithMove k q) -> Event x (DMap k v) mergeWithMove nt d = cacheEvent (mergeCheapWithMove nt d) {-# INLINE [1] mergeCheap #-} mergeCheap :: forall k x q v. (HasSpiderTimeline x, GCompare k) => (forall a. q a -> Event x (v a))- -> Dynamic x (PatchDMap k q)+ -> DynamicS x (PatchDMap k q) -> Event x (DMap k v) mergeCheap nt = mergeGCheap' getInitialSubscribers updateMe destroy where@@ -1742,7 +1770,7 @@ let s = subscriber $ return k (subscription@(EventSubscription _ parentSubd), parentOcc) <- subscribeAndRead (nt e) s height <- liftIO $ getEventSubscribedHeight parentSubd- return (fmap (\x -> k :=> x) parentOcc, height, k :=> MergeSubscribedParent subscription)+ return (fmap (k :=>) parentOcc, height, k :=> MergeSubscribedParent subscription) return ( DMap.fromDistinctAscList $ mapMaybe (\(x, _, _) -> x) subscribers , fmap (\(_, h, _) -> h) subscribers --TODO: Assert that there's no invalidHeight in here , DMap.fromDistinctAscList $ map (\(_, _, x) -> x) subscribers@@ -1754,7 +1782,7 @@ {-# INLINE [1] mergeCheapWithMove #-} mergeCheapWithMove :: forall k x v q. (HasSpiderTimeline x, GCompare k) => (forall a. q a -> Event x (v a))- -> Dynamic x (PatchDMapWithMove k q)+ -> DynamicS x (PatchDMapWithMove k q) -> Event x (DMap k v) mergeCheapWithMove nt = mergeGCheap' getInitialSubscribers updateMe destroy where@@ -1790,7 +1818,7 @@ let s = subscriber $ liftIO $ readIORef keyRef (subscription@(EventSubscription _ parentSubd), parentOcc) <- subscribeAndRead (nt e) s height <- liftIO $ getEventSubscribedHeight parentSubd- return (fmap (\x -> k :=> x) parentOcc, height, k :=> MergeSubscribedParentWithMove subscription keyRef)+ return (fmap (k :=>) parentOcc, height, k :=> MergeSubscribedParentWithMove subscription keyRef) return ( DMap.fromDistinctAscList $ mapMaybe (\(x, _, _) -> x) subscribers , fmap (\(_, h, _) -> h) subscribers --TODO: Assert that there's no invalidHeight in here , DMap.fromDistinctAscList $ map (\(_, _, x) -> x) subscribers@@ -1902,7 +1930,7 @@ {-# INLINE mergeGCheap' #-} mergeGCheap' :: forall k v x p s q. (HasSpiderTimeline x, GCompare k, PatchTarget p ~ DMap k q)- => MergeInitFunc k v q x s -> MergeUpdateFunc k v x p s -> MergeDestroyFunc k s -> Dynamic x p -> Event x (DMap k v)+ => MergeInitFunc k v q x s -> MergeUpdateFunc k v x p s -> MergeDestroyFunc k s -> DynamicS x p -> Event x (DMap k v) mergeGCheap' getInitialSubscribers updateFunc destroy d = Event $ \sub -> do initialParents <- readBehaviorUntracked $ dynamicCurrent d accumRef <- liftIO $ newIORef $ error "merge: accumRef not yet initialized"@@ -1951,11 +1979,11 @@ , occ ) -mergeInt :: forall x a. (HasSpiderTimeline x) => Dynamic x (PatchIntMap (Event x a)) -> Event x (IntMap a)+mergeInt :: forall x a. (HasSpiderTimeline x) => DynamicS x (PatchIntMap (Event x a)) -> Event x (IntMap a) mergeInt = cacheEvent . mergeIntCheap {-# INLINABLE mergeIntCheap #-}-mergeIntCheap :: forall x a. (HasSpiderTimeline x) => Dynamic x (PatchIntMap (Event x a)) -> Event x (IntMap a)+mergeIntCheap :: forall x a. (HasSpiderTimeline x) => DynamicS x (PatchIntMap (Event x a)) -> Event x (IntMap a) mergeIntCheap d = Event $ \sub -> do initialParents <- readBehaviorUntracked $ dynamicCurrent d accum <- liftIO $ FastMutableIntMap.newEmpty@@ -2115,7 +2143,7 @@ -- | Run an event action outside of a frame runFrame :: forall x a. HasSpiderTimeline x => EventM x a -> SpiderHost x a --TODO: This function also needs to hold the mutex runFrame a = SpiderHost $ do- let env = _spiderTimeline_eventEnv (spiderTimeline :: SpiderTimelineEnv x)+ let env = _spiderTimeline_eventEnv $ unSTE (spiderTimeline :: SpiderTimelineEnv x) let go = do result <- a runHoldInits (eventEnvHoldInits env) (eventEnvDynInits env) (eventEnvMergeInits env) -- This must happen before doing the assignments, in case subscribing a Hold causes existing Holds to be read by the newly-propagated events@@ -2326,7 +2354,7 @@ fail _ = error "Dynamic does not support 'fail'" {-# INLINABLE newJoinDyn #-}-newJoinDyn :: HasSpiderTimeline x => Reflex.Spider.Internal.Dynamic x (Identity (Reflex.Spider.Internal.Dynamic x (Identity a))) -> Reflex.Spider.Internal.Dyn x (Identity a)+newJoinDyn :: HasSpiderTimeline x => DynamicS x (Identity (DynamicS x (Identity a))) -> Reflex.Spider.Internal.Dyn x (Identity a) newJoinDyn d = let readV0 = readBehaviorTracked . dynamicCurrent =<< readBehaviorTracked (dynamicCurrent d) eOuter = Reflex.Spider.Internal.push (fmap (Just . Identity) . readBehaviorUntracked . dynamicCurrent . runIdentity) $ dynamicUpdated d@@ -2476,7 +2504,7 @@ #ifdef DEBUG depthRef <- newIORef 0 #endif- return $ SpiderTimelineEnv+ return $ STE $ SpiderTimelineEnv { _spiderTimeline_lock = lock , _spiderTimeline_eventEnv = env #ifdef DEBUG@@ -2492,13 +2520,13 @@ instance Reifies s (SpiderTimelineEnv x) => HasSpiderTimeline (LocalSpiderTimeline x s) where- spiderTimeline = localSpiderTimeline (Proxy :: Proxy s) $ reflect (Proxy :: Proxy s)+ spiderTimeline = localSpiderTimeline Proxy $ reflect (Proxy :: Proxy s) localSpiderTimeline- :: Proxy s+ :: proxy s -> SpiderTimelineEnv x -> SpiderTimelineEnv (LocalSpiderTimeline x s)-localSpiderTimeline _ = unsafeCoerce+localSpiderTimeline _ = coerce -- | Pass a new timeline to the given function. withSpiderTimeline :: (forall x. HasSpiderTimeline x => SpiderTimelineEnv x -> IO r) -> IO r@@ -2516,8 +2544,8 @@ {-# SPECIALIZE instance R.Reflex (SpiderTimeline Global) #-} newtype Behavior (SpiderTimeline x) a = SpiderBehavior { unSpiderBehavior :: Behavior x a } newtype Event (SpiderTimeline x) a = SpiderEvent { unSpiderEvent :: Event x a }- newtype Dynamic (SpiderTimeline x) a = SpiderDynamic { unSpiderDynamic :: Dynamic x (Identity a) } -- deriving (Functor, Applicative, Monad)- newtype Incremental (SpiderTimeline x) p = SpiderIncremental { unSpiderIncremental :: Dynamic x p }+ newtype Dynamic (SpiderTimeline x) a = SpiderDynamic { unSpiderDynamic :: DynamicS x (Identity a) } -- deriving (Functor, Applicative, Monad)+ newtype Incremental (SpiderTimeline x) p = SpiderIncremental { unSpiderIncremental :: DynamicS x p } type PullM (SpiderTimeline x) = SpiderPullM x type PushM (SpiderTimeline x) = SpiderPushM x {-# INLINABLE never #-}@@ -2546,7 +2574,7 @@ {-# INLINABLE current #-} current = SpiderBehavior . dynamicCurrent . unSpiderDynamic {-# INLINABLE updated #-}- updated = coerce $ SpiderEvent . dynamicUpdated . unSpiderDynamic+ updated = SpiderEvent #. dynamicUpdated .# fmap coerce . unSpiderDynamic {-# INLINABLE unsafeBuildDynamic #-} unsafeBuildDynamic readV0 v' = SpiderDynamic $ dynamicDynIdentity $ unsafeBuildDynamic (coerce readV0) $ coerce $ unSpiderEvent v' {-# INLINABLE unsafeBuildIncremental #-}@@ -2565,9 +2593,10 @@ return $ Identity <$> apply p c --TODO: Avoid the redundant 'apply' eventCoercion Coercion = Coercion behaviorCoercion Coercion = Coercion- dynamicCoercion = unsafeCoerce --TODO: How can we avoid this unsafeCoerce? This is safe only because we know how Identity works as a Patch instance+ dynamicCoercion Coercion = Coercion+ incrementalCoercion Coercion Coercion = Coercion {-# INLINABLE mergeIntIncremental #-}- mergeIntIncremental = SpiderEvent . mergeInt . (unsafeCoerce :: Dynamic x (PatchIntMap (R.Event (SpiderTimeline x) a)) -> Dynamic x (PatchIntMap (Event x a))) . unSpiderIncremental+ mergeIntIncremental = SpiderEvent . mergeInt . coerce {-# INLINABLE fanInt #-} fanInt e = R.EventSelectorInt $ SpiderEvent . selectInt (fanInt (unSpiderEvent e))
src/Reflex/TriggerEvent/Class.hs view
@@ -2,7 +2,6 @@ -- new 'Event's that can be triggered from 'IO'. {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE UndecidableInstances #-} module Reflex.TriggerEvent.Class ( TriggerEvent (..)
test/EventWriterT.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE BangPatterns #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-}@@ -13,6 +14,10 @@ import qualified Data.Map as M import Data.These +#if defined(MIN_VERSION_these_lens) || (MIN_VERSION_these(0,8,0) && !MIN_VERSION_these(0,9,0))+import Data.These.Lens+#endif+ import Reflex import Reflex.EventWriter.Base import Test.Run@@ -48,16 +53,13 @@ return e testOrdering :: (Reflex t, Monad m) => Event t () -> EventWriterT t [Int] m ()-testOrdering pulse = do- forM_ [10,9..1] $ \i -> tellEvent ([i] <$ pulse)- return ()+testOrdering pulse = forM_ [10,9..1] $ \i -> tellEvent ([i] <$ pulse) testSimultaneous :: (Reflex t, Adjustable t m, MonadHold t m) => Event t (These () ()) -> EventWriterT t [Int] m () testSimultaneous pulse = do let e0 = fmapMaybe (^? here) pulse e1 = fmapMaybe (^? there) pulse forM_ [1,3..9] $ \i -> runWithReplace (tellEvent ([i] <$ e0)) $ ffor e1 $ \_ -> tellEvent ([i+1] <$ e0)- return () -- | Test that a widget telling and event which fires at the same time it has been replaced -- doesn't count along with the new widget.
test/QueryT.hs view
@@ -19,6 +19,10 @@ import Data.Semigroup import Data.These +#if defined(MIN_VERSION_these_lens) || (MIN_VERSION_these(0,8,0) && !MIN_VERSION_these(0,9,0))+import Data.These.Lens+#endif+ import Reflex import Reflex.Patch.MapWithMove import Test.Run
test/Reflex/Bench/Focused.hs view
@@ -130,6 +130,16 @@ joinDynChain :: (Reflex t, MonadHold t m) => Word -> Dynamic t Word -> m (Dynamic t Word) joinDynChain = iterM (\d -> return $ join $ fmap (const d) d) +holdDynChain :: (Reflex t, MonadHold t m) => Word -> Dynamic t Word -> m (Dynamic t Word)+holdDynChain = iterM (\d -> sample (current d) >>= flip holdDyn (updated d))++buildDynChain :: (Reflex t, MonadHold t m) => Word -> Dynamic t Word -> m (Dynamic t Word)+buildDynChain = iterM (\d -> do + let b = fmap (+1) (current d)+ e = fmap (*2) (updated d)+ buildDynamic (sample b) e)++ combineDynChain :: (Reflex t, MonadHold t m) => Word -> Dynamic t Word -> m (Dynamic t Word) combineDynChain = iterM (\d -> return $ zipDynWith (+) d d) @@ -308,6 +318,8 @@ dynamics n = [ testE "mapDynChain" $ fmap updated $ mapDynChain n =<< d , testE "joinDynChain" $ fmap updated $ joinDynChain n =<< d+ , testE "holdDynChain" $ fmap updated $ holdDynChain n =<< d+ , testE "buildDynChain" $ fmap updated $ buildDynChain n =<< d , testE "combineDynChain" $ fmap updated $ combineDynChain n =<< d , testE "dense mergeTree" $ fmap (updated . mergeTreeDyn 8) dense , testE "sparse mergeTree" $ fmap (updated . mergeTreeDyn 8) sparse
test/Reflex/Test/CrossImpl.hs view
@@ -218,6 +218,11 @@ bb <- hold b $ pushAlways (const $ hold "asdf" eo) eo let b' = pull $ sample =<< sample bb return (b', e)+ , (,) "foldDynWhileFiring" $ TestCase (Map.singleton 0 "zxc", Map.fromList [(1, "qwer"), (2, "lkj")]) $ \(_, e) -> do+ d <- foldDyn (:) [] $+ pushAlways (\a -> foldDyn (:) [a] e) e+ let b = current (join (fmap distributeListOverDynPure d))+ return (b, e) , (,) "joinDyn" $ TestCase (Map.singleton 0 (0 :: Int), Map.fromList [(1, "qwer"), (2, "lkj")]) $ \(b, e) -> do bb <- hold "b" e bd <- hold never . fmap (const e) =<< headE e
test/RequesterT.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE BangPatterns #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-}@@ -14,6 +15,10 @@ import Data.Functor.Misc import qualified Data.Map as M import Data.These++#if defined(MIN_VERSION_these_lens) || (MIN_VERSION_these(0,8,0) && !MIN_VERSION_these(0,9,0))+import Data.These.Lens+#endif import Reflex import Reflex.Requester.Base
test/hlint.hs view
@@ -22,6 +22,7 @@ , "--ignore=Use unless" , "--ignore=Reduce duplication" , "--cpp-define=USE_TEMPLATE_HASKELL"+ , "--ignore=Use tuple-section" ] recurseInto = and <$> sequence [ fileType ==? Directory