1-- | This module provides 'PerformEventT', the standard implementation of
4{-# LANGUAGE ExistentialQuantification #-}
5{-# LANGUAGE FlexibleContexts #-}
6{-# LANGUAGE FlexibleInstances #-}
8{-# LANGUAGE GeneralizedNewtypeDeriving #-}
9{-# LANGUAGE MultiParamTypeClasses #-}
10{-# LANGUAGE PartialTypeSignatures #-}
11{-# LANGUAGE PolyKinds #-}
12{-# LANGUAGE RankNTypes #-}
13{-# LANGUAGE ScopedTypeVariables #-}
14{-# LANGUAGE StandaloneDeriving #-}
15{-# LANGUAGE TypeFamilies #-}
16{-# LANGUAGE TypeOperators #-}
17{-# LANGUAGE UndecidableInstances #-}
18#ifdef USE_REFLEX_OPTIMIZER
19{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
21module Reflex.PerformEvent.Base
28import Reflex.Adjustable.Class
29import Reflex.Host.Class
30import Reflex.PerformEvent.Class
31import Reflex.Requester.Base
32import Reflex.Requester.Class
35import Control.Monad.Exception
36import Control.Monad.Identity
37import Control.Monad.Primitive
38import Control.Monad.Reader
39import Control.Monad.Ref
41import Data.Dependent.Map (DMap)
42import qualified Data.Dependent.Map as DMap
43import Data.Dependent.Sum
44import Data.IntMap.Strict (IntMap)
45import qualified Data.IntMap.Strict as IntMap
46import qualified Data.Semigroup as S
48-- | A function that fires events for the given 'EventTrigger's and then runs
49-- any followup actions provided via 'PerformEvent'. The given 'ReadPhase'
50-- action will be run once for the initial trigger execution as well as once for
52newtype FireCommand t m = FireCommand { runFireCommand :: forall a. [DSum (EventTrigger t) Identity] -> ReadPhase m a -> m [a] } --TODO: The handling of this ReadPhase seems wrong, or at least inelegant; how do we actually make the decision about what order frames run in?
54-- | Provides a basic implementation of 'PerformEvent'. Note that, despite the
55-- name, 'PerformEventT' is not an instance of 'MonadTrans'.
56newtype PerformEventT t m a = PerformEventT { unPerformEventT :: RequesterT t (HostFrame t) Identity (HostFrame t) a }
58deriving instance ReflexHost t => Functor (PerformEventT t m)
59deriving instance ReflexHost t => Applicative (PerformEventT t m)
60deriving instance ReflexHost t => Monad (PerformEventT t m)
61deriving instance ReflexHost t => MonadFix (PerformEventT t m)
62deriving instance (ReflexHost t, MonadIO (HostFrame t)) => MonadIO (PerformEventT t m)
63deriving instance (ReflexHost t, MonadException (HostFrame t)) => MonadException (PerformEventT t m)
64deriving instance (ReflexHost t, Monoid a) => Monoid (PerformEventT t m a)
65deriving instance (ReflexHost t, S.Semigroup a) => S.Semigroup (PerformEventT t m a)
67instance (PrimMonad (HostFrame t), ReflexHost t) => PrimMonad (PerformEventT t m) where
68 type PrimState (PerformEventT t m) = PrimState (HostFrame t)
69 primitive = PerformEventT . lift . primitive
71instance (ReflexHost t, Ref m ~ Ref IO) => PerformEvent t (PerformEventT t m) where
72 type Performable (PerformEventT t m) = HostFrame t
73 {-# INLINABLE performEvent_ #-}
74 performEvent_ = PerformEventT . requesting_
75 {-# INLINABLE performEvent #-}
76 performEvent = PerformEventT . requestingIdentity
78instance (ReflexHost t, PrimMonad (HostFrame t)) => Adjustable t (PerformEventT t m) where
79 runWithReplace outerA0 outerA' = PerformEventT $ runWithReplaceRequesterTWith f (coerce outerA0) (coerceEvent outerA')
80 where f :: HostFrame t a -> Event t (HostFrame t b) -> RequesterT t (HostFrame t) Identity (HostFrame t) (a, Event t b)
83 result' <- requestingIdentity a'
84 return (result0, result')
85 traverseIntMapWithKeyWithAdjust f outerDm0 outerDm' = PerformEventT $ traverseIntMapWithKeyWithAdjustRequesterTWith (defaultAdjustIntBase traverseIntMapPatchWithKey) patchIntMapNewElementsMap mergeIntIncremental (\k v -> unPerformEventT $ f k v) (coerce outerDm0) (coerceEvent outerDm')
86 traverseDMapWithKeyWithAdjust f outerDm0 outerDm' = PerformEventT $ traverseDMapWithKeyWithAdjustRequesterTWith (defaultAdjustBase traversePatchDMapWithKey) mapPatchDMap weakenPatchDMapWith patchMapNewElementsMap mergeMapIncremental (\k v -> unPerformEventT $ f k v) (coerce outerDm0) (coerceEvent outerDm')
87 traverseDMapWithKeyWithAdjustWithMove f outerDm0 outerDm' = PerformEventT $ traverseDMapWithKeyWithAdjustRequesterTWith (defaultAdjustBase traversePatchDMapWithMoveWithKey) mapPatchDMapWithMove weakenPatchDMapWithMoveWith patchMapWithMoveNewElementsMap mergeMapIncrementalWithMove (\k v -> unPerformEventT $ f k v) (coerce outerDm0) (coerceEvent outerDm')
89defaultAdjustBase :: forall t v v2 k' p. (Monad (HostFrame t), PrimMonad (HostFrame t), Reflex t)
90 => ((forall a. k' a -> v a -> HostFrame t (v2 a)) -> p k' v -> HostFrame t (p k' v2))
91 -> (forall a. k' a -> v a -> HostFrame t (v2 a))
94 -> RequesterT t (HostFrame t) Identity (HostFrame t) (DMap k' v2, Event t (p k' v2))
95defaultAdjustBase traversePatchWithKey f' dm0 dm' = do
96 result0 <- lift $ DMap.traverseWithKey f' dm0
97 result' <- requestingIdentity $ ffor dm' $ traversePatchWithKey f'
98 return (result0, result')
100defaultAdjustIntBase :: forall t v v2 p. (Monad (HostFrame t), PrimMonad (HostFrame t), Reflex t)
101 => ((IntMap.Key -> v -> HostFrame t v2) -> p v -> HostFrame t (p v2))
102 -> (IntMap.Key -> v -> HostFrame t v2)
105 -> RequesterT t (HostFrame t) Identity (HostFrame t) (IntMap v2, Event t (p v2))
106defaultAdjustIntBase traversePatchWithKey f' dm0 dm' = do
107 result0 <- lift $ IntMap.traverseWithKey f' dm0
108 result' <- requestingIdentity $ ffor dm' $ traversePatchWithKey f'
109 return (result0, result')
111instance ReflexHost t => MonadReflexCreateTrigger t (PerformEventT t m) where
112 {-# INLINABLE newEventWithTrigger #-}
113 newEventWithTrigger = PerformEventT . lift . newEventWithTrigger
114 {-# INLINABLE newFanEventWithTrigger #-}
115 newFanEventWithTrigger f = PerformEventT $ lift $ newFanEventWithTrigger f
117-- | Run a 'PerformEventT' action, returning a 'FireCommand' that allows the
118-- caller to trigger 'Event's while ensuring that 'performEvent' actions are run
119-- at the appropriate time.
120{-# INLINABLE hostPerformEventT #-}
121hostPerformEventT :: forall t m a.
123 , MonadSubscribeEvent t m
124 , MonadReflexHost t m
128 => PerformEventT t m a
129 -> m (a, FireCommand t m)
130hostPerformEventT a = do
131 (response, responseTrigger) <- newEventWithTriggerRef
132 (result, eventToPerform) <- runHostFrame $ runRequesterT (unPerformEventT a) response
133 eventToPerformHandle <- subscribeEvent eventToPerform
134 return $ (,) result $ FireCommand $ \triggers (readPhase :: ReadPhase m a') -> do
135 let go :: [DSum (EventTrigger t) Identity] -> m [a']
137 (result', mToPerform) <- fireEventsAndRead ts $ do
138 mToPerform <- sequence =<< readEvent eventToPerformHandle
140 return (result', mToPerform)
142 Nothing -> return [result']
144 responses <- runHostFrame $ traverseRequesterData (fmap Identity) toPerform
145 mrt <- readRef responseTrigger
146 let followupEventTriggers = case mrt of
147 Just rt -> [rt :=> Identity responses]
149 (result':) <$> go followupEventTriggers
152instance ReflexHost t => MonadSample t (PerformEventT t m) where
153 {-# INLINABLE sample #-}
154 sample = PerformEventT . lift . sample
156instance (ReflexHost t, MonadHold t m) => MonadHold t (PerformEventT t m) where
157 {-# INLINABLE hold #-}
158 hold v0 v' = PerformEventT $ lift $ hold v0 v'
159 {-# INLINABLE holdDyn #-}
160 holdDyn v0 v' = PerformEventT $ lift $ holdDyn v0 v'
161 {-# INLINABLE holdIncremental #-}
162 holdIncremental v0 v' = PerformEventT $ lift $ holdIncremental v0 v'
163 {-# INLINABLE buildDynamic #-}
164 buildDynamic getV0 v' = PerformEventT $ lift $ buildDynamic getV0 v'
165 {-# INLINABLE headE #-}
166 headE = PerformEventT . lift . headE
168instance (MonadRef (HostFrame t), ReflexHost t) => MonadRef (PerformEventT t m) where
169 type Ref (PerformEventT t m) = Ref (HostFrame t)
170 {-# INLINABLE newRef #-}
171 newRef = PerformEventT . lift . newRef
172 {-# INLINABLE readRef #-}
173 readRef = PerformEventT . lift . readRef
174 {-# INLINABLE writeRef #-}
175 writeRef r = PerformEventT . lift . writeRef r
177instance (MonadAtomicRef (HostFrame t), ReflexHost t) => MonadAtomicRef (PerformEventT t m) where
178 {-# INLINABLE atomicModifyRef #-}
179 atomicModifyRef r = PerformEventT . lift . atomicModifyRef r
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list