1-- | This module defines 'PostBuildT', the standard implementation of
4{-# LANGUAGE DataKinds #-}
5{-# LANGUAGE FlexibleInstances #-}
6{-# LANGUAGE GeneralizedNewtypeDeriving #-}
7{-# LANGUAGE MultiParamTypeClasses #-}
8{-# LANGUAGE RankNTypes #-}
9{-# LANGUAGE RecursiveDo #-}
10{-# LANGUAGE ScopedTypeVariables #-}
11{-# LANGUAGE TypeFamilies #-}
12{-# LANGUAGE TypeOperators #-}
13{-# LANGUAGE UndecidableInstances #-}
14#ifdef USE_REFLEX_OPTIMIZER
15{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
17module Reflex.PostBuild.Base
21 , mapIntMapWithAdjustImpl
22 , mapDMapWithAdjustImpl
26import Reflex.Host.Class
27import Reflex.PerformEvent.Class
28import Reflex.PostBuild.Class
29import Reflex.TriggerEvent.Class
31import Control.Monad.Exception
32import Control.Monad.Identity
33import Control.Monad.Primitive
34import Control.Monad.Reader
35import Control.Monad.Ref
36import Control.Monad.Trans.Control
37import Data.Dependent.Map (DMap)
38import qualified Data.Dependent.Map as DMap
39import Data.Functor.Compose
40import Data.IntMap.Strict (IntMap)
41import qualified Data.IntMap.Strict as IntMap
43-- | Provides a basic implementation of 'PostBuild'.
44newtype PostBuildT t m a = PostBuildT { unPostBuildT :: ReaderT (Event t ()) m a } deriving (Functor, Applicative, Monad, MonadFix, MonadIO, MonadTrans, MonadException, MonadAsyncException)
46-- | Run a 'PostBuildT' action. An 'Event' should be provided that fires
47-- immediately after the action is finished running; no other 'Event's should
49{-# INLINABLE runPostBuildT #-}
50runPostBuildT :: PostBuildT t m a -> Event t () -> m a
51runPostBuildT (PostBuildT a) = runReaderT a
53instance PrimMonad m => PrimMonad (PostBuildT x m) where
54 type PrimState (PostBuildT x m) = PrimState m
55 primitive = lift . primitive
57instance MonadTransControl (PostBuildT t) where
58 type StT (PostBuildT t) a = StT (ReaderT (Event t ())) a
59 {-# INLINABLE liftWith #-}
60 liftWith = defaultLiftWith PostBuildT unPostBuildT
61 {-# INLINABLE restoreT #-}
62 restoreT = defaultRestoreT PostBuildT
64instance (Reflex t, Monad m) => PostBuild t (PostBuildT t m) where
65 {-# INLINABLE getPostBuild #-}
66 getPostBuild = PostBuildT ask
68instance MonadSample t m => MonadSample t (PostBuildT t m) where
69 {-# INLINABLE sample #-}
70 sample = lift . sample
72instance MonadHold t m => MonadHold t (PostBuildT t m) where
73 {-# INLINABLE hold #-}
74 hold v0 = lift . hold v0
75 {-# INLINABLE holdDyn #-}
76 holdDyn v0 = lift . holdDyn v0
77 {-# INLINABLE holdIncremental #-}
78 holdIncremental v0 = lift . holdIncremental v0
80instance PerformEvent t m => PerformEvent t (PostBuildT t m) where
81 type Performable (PostBuildT t m) = PostBuildT t (Performable m)
82 {-# INLINABLE performEvent_ #-}
83 performEvent_ e = liftWith $ \run -> performEvent_ $ fmap run e
84 {-# INLINABLE performEvent #-}
85 performEvent e = liftWith $ \run -> performEvent $ fmap run e
87instance (ReflexHost t, MonadReflexCreateTrigger t m) => MonadReflexCreateTrigger t (PostBuildT t m) where
88 {-# INLINABLE newEventWithTrigger #-}
89 newEventWithTrigger = PostBuildT . lift . newEventWithTrigger
90 {-# INLINABLE newFanEventWithTrigger #-}
91 newFanEventWithTrigger f = PostBuildT $ lift $ newFanEventWithTrigger f
93instance TriggerEvent t m => TriggerEvent t (PostBuildT t m) where
94 {-# INLINABLE newTriggerEvent #-}
95 newTriggerEvent = lift newTriggerEvent
96 {-# INLINABLE newTriggerEventWithOnComplete #-}
97 newTriggerEventWithOnComplete = lift newTriggerEventWithOnComplete
98 newEventWithLazyTriggerWithOnComplete = lift . newEventWithLazyTriggerWithOnComplete
100instance MonadRef m => MonadRef (PostBuildT t m) where
101 type Ref (PostBuildT t m) = Ref m
102 {-# INLINABLE newRef #-}
103 newRef = lift . newRef
104 {-# INLINABLE readRef #-}
105 readRef = lift . readRef
106 {-# INLINABLE writeRef #-}
107 writeRef r = lift . writeRef r
109instance MonadAtomicRef m => MonadAtomicRef (PostBuildT t m) where
110 {-# INLINABLE atomicModifyRef #-}
111 atomicModifyRef r = lift . atomicModifyRef r
113instance (Reflex t, MonadHold t m, MonadFix m, MonadAdjust t m, PerformEvent t m) => MonadAdjust t (PostBuildT t m) where
114 runWithReplace a0 a' = do
115 postBuild <- getPostBuild
117 rec result@(_, result') <- runWithReplace (runPostBuildT a0 postBuild) $ fmap (\v -> runPostBuildT v =<< headE voidResult') a'
118 let voidResult' = fmapCheap (\_ -> ()) result'
120 {-# INLINABLE traverseIntMapWithKeyWithAdjust #-}
121 traverseIntMapWithKeyWithAdjust = mapIntMapWithAdjustImpl traverseIntMapWithKeyWithAdjust
122 {-# INLINABLE traverseDMapWithKeyWithAdjust #-}
123 traverseDMapWithKeyWithAdjust = mapDMapWithAdjustImpl traverseDMapWithKeyWithAdjust mapPatchDMap
124 traverseDMapWithKeyWithAdjustWithMove = mapDMapWithAdjustImpl traverseDMapWithKeyWithAdjustWithMove mapPatchDMapWithMove
126{-# INLINABLE mapIntMapWithAdjustImpl #-}
127mapIntMapWithAdjustImpl :: forall t m v v' p. (Reflex t, MonadFix m, MonadHold t m, Functor p)
128 => ( (IntMap.Key -> ((Bool, Event t ()), v) -> m v')
129 -> IntMap ((Bool, Event t ()), v)
130 -> Event t (p ((Bool, Event t ()), v))
131 -> m (IntMap v', Event t (p v'))
133 -> (IntMap.Key -> v -> PostBuildT t m v')
136 -> PostBuildT t m (IntMap v', Event t (p v'))
137mapIntMapWithAdjustImpl base f dm0 dm' = do
138 postBuild <- getPostBuild
139 let loweredDm0 = fmap ((,) (False, postBuild)) dm0
140 f' :: IntMap.Key -> ((Bool, Event t ()), v) -> m v'
141 f' k ((shouldHeadE, e), v) = do
142 eOnce <- if shouldHeadE
143 then headE e --TODO: Avoid doing this headE so many times; once per loweredDm' firing ought to be OK, but it's not totally trivial to do because result' might be firing at the same time, and we don't want *that* to be the postBuild occurrence
145 runPostBuildT (f k v) eOnce
147 rec (result0, result') <- base f' loweredDm0 loweredDm'
148 let voidResult' = fmapCheap (\_ -> ()) result'
149 let loweredDm' = ffor dm' $ fmap ((,) (True, voidResult'))
150 return (result0, result')
152{-# INLINABLE mapDMapWithAdjustImpl #-}
153mapDMapWithAdjustImpl :: forall t m k v v' p. (Reflex t, MonadFix m, MonadHold t m)
154 => ( (forall a. k a -> Compose ((,) (Bool, Event t ())) v a -> m (v' a))
155 -> DMap k (Compose ((,) (Bool, Event t ())) v)
156 -> Event t (p k (Compose ((,) (Bool, Event t ())) v))
157 -> m (DMap k v', Event t (p k v'))
159 -> ((forall a. v a -> Compose ((,) (Bool, Event t ())) v a) -> p k v -> p k (Compose ((,) (Bool, Event t ())) v))
160 -> (forall a. k a -> v a -> PostBuildT t m (v' a))
163 -> PostBuildT t m (DMap k v', Event t (p k v'))
164mapDMapWithAdjustImpl base mapPatch f dm0 dm' = do
165 postBuild <- getPostBuild
166 let loweredDm0 = DMap.map (Compose . (,) (False, postBuild)) dm0
167 f' :: forall a. k a -> Compose ((,) (Bool, Event t ())) v a -> m (v' a)
168 f' k (Compose ((shouldHeadE, e), v)) = do
169 eOnce <- if shouldHeadE
170 then headE e --TODO: Avoid doing this headE so many times; once per loweredDm' firing ought to be OK, but it's not totally trivial to do because result' might be firing at the same time, and we don't want *that* to be the postBuild occurrence
172 runPostBuildT (f k v) eOnce
174 rec (result0, result') <- base f' loweredDm0 loweredDm'
175 let voidResult' = fmapCheap (\_ -> ()) result'
176 let loweredDm' = ffor dm' $ mapPatch (Compose . (,) (True, voidResult'))
177 return (result0, result')
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