2{-# LANGUAGE ConstraintKinds #-}
3{-# LANGUAGE FlexibleContexts #-}
5{-# LANGUAGE RecursiveDo #-}
6{-# LANGUAGE ScopedTypeVariables #-}
7{-# LANGUAGE PatternSynonyms #-}
8{-# LANGUAGE RankNTypes #-}
14import Control.Applicative
16import Control.Monad.Fix
17import Control.Exception
19import Data.Maybe (isJust)
20import Data.Functor.Misc
21import qualified Data.Map as Map
23import qualified Data.IntMap as IntMap
24import Data.IntMap (IntMap)
28import Reflex.EventWriter.Base
31import Reflex.Spider.Internal (EventLoopException)
32import Data.Witherable (Filterable)
34#if defined(MIN_VERSION_these_lens) || (MIN_VERSION_these(0,8,0) && !MIN_VERSION_these(0,9,0))
38type Widget t m = (MonadHold t m, Reflex t, MonadFix m)
40connectDyn :: Widget t m => Event t () -> (Dynamic t a, Dynamic t a) -> m (Dynamic t a)
41connectDyn e (d, d') = do
42 dd <- holdDyn d (d' <$ e)
45dynLoop :: Widget t m => (Event t Int, Event t ()) -> m (Event t Int)
47 -- "heightBagRemove: Height 2 not present in bag HeightBag {_heightBag_size = 2, _heightBag_contents = fromList [(0,1)]}"
50 d' <- connectDyn e2 (d, liftA2 (+) d d')
53connectOnCoincidence :: Widget t m => Event t () -> Event t a -> m (Event t a)
54connectOnCoincidence click e = do
55 d <- holdDyn never (e <$ click)
56 return $ coincidence (updated d)
58coincidenceLoop :: Widget t m => (Event t Int, Event t ()) -> m (Event t Int)
59coincidenceLoop (e1, e2) = do
60-- "heightBagRemove: Height 1 not present in bag HeightBag {_heightBag_size = 1, _heightBag_contents = fromList [(0,0)]}"
61-- (simpler version of dynLoop)
63 e' <- connectOnCoincidence e2 (updated d)
64 d <- count (align e' e1)
67addHeight :: Reflex t => Event t a -> Event t a
68addHeight e = leftmost [e4, e4] where
70 e2 = leftmost [e1, e1]
71 e3 = leftmost [e2, e2]
72 e4 = leftmost [e3, e3]
74-- Take an existing test and build it inside a
75buildLoop :: Widget t m => (forall t m. Widget t m => (Event t Int, Event t ()) -> m (Event t Int)) -> (Event t Int, Event t ()) -> m (Event t Int)
76buildLoop test (e1, e2) = switchHold never buildLoop
77 where buildLoop = pushAlways (const $ test (e1, e2)) e2
79connectButtonPromptly :: Widget t m => Event t () -> Event t a -> m (Event t a)
80connectButtonPromptly click e = do
81 d <- holdDyn never (e <$ click)
84connectButton :: Widget t m => Event t () -> Event t a -> m (Event t a)
85connectButton click e = do
86 d <- hold never (e <$ click)
89switchLoop01 :: Widget t m => (Event t Int, Event t ()) -> m (Event t Int)
90switchLoop01 (e1, e2) = do
92 e' <- connectButton e2 (updated d)
93 d <- count (align e' e1)
96mergeLoop :: forall t m. (Adjustable t m, Widget t m) => (Event t Int, Event t ()) -> m (Event t Int)
97mergeLoop (e1, e2) = do
99 (_, e) <- runEventWriterT $
100 runWithReplace w (leftmost [w <$ e1])
105 tellEvent (updated ((pure <$> c) :: Dynamic t [Int]))
107switchLoop02 :: Widget t m => (Event t Int, Event t ()) -> m (Event t Int)
108switchLoop02 (e1, e2) = do
110 e' <- connectButton e2 (updated d)
111 d <- count (leftmost [e', e1])
114switchLoop03 :: Widget t m => (Event t Int, Event t ()) -> m (Event t Int)
115switchLoop03 (e1, e2) = do
117 e' <- connectButton e2 (addHeight $ updated d)
118 d <- count (align e' e1)
121staticLoop01 :: Widget t m => (Event t Int, Event t ()) -> m (Event t Int)
122staticLoop01 (e1, e2) = do
124 d <- foldDyn (+) (0 :: Int) (1 <$ align e1 (updated d))
127staticLoop02 :: Widget t m => (Event t Int, Event t ()) -> m (Event t Int)
128staticLoop02 (e1, e2) = do
130 d <- foldDyn (+) (0 :: Int) (leftmost [e1, updated d])
133buildStaticLoop :: Widget t m => (Event t Int, Event t ()) -> m (Event t Int)
134buildStaticLoop (e1, e2) = switchHold never buildLoop
135 where buildLoop = pushAlways (const $ staticLoop01 (e1, e2)) e2
137splitThese :: Filterable f => f (These a b) -> (f a, f b)
138splitThese f = (mapMaybe (preview here) f, mapMaybe (preview there) f)
142 describe "DebugCycles" $ do
143 it "throws EventLoopException on switchLoop01" $ do
145 it "throws EventLoopException on switchLoop02" $ do
147 it "throws EventLoopException on switchLoop03" $ do
149 it "throws EventLoopException on buildSwitchLoop" $ do
150 check $ buildLoop switchLoop01
151 xit "throws EventLoopException on mergeLoop" $ do
153 xit "throws EventLoopException on staticLoop01" $ do
155 xit "throws EventLoopException on staticLoop02" $ do
157 xit "throws EventLoopException on buildStaticLoop" $ do
158 check buildStaticLoop
159 xit "throws EventLoopException on coincidenceLoop" $ do
160 check coincidenceLoop
161 xit "throws EventLoopException on dynLoop" $ do
163 xit "throws EventLoopException on buildCoincidenceLoop" $ do
164 check $ buildLoop coincidenceLoop
166 milliseconds = (*1000)
167 occs = [ This 1, This 2, That (), This 3, That (), This 1 ]
169 let action = timeout (milliseconds 50) $ do
170 runApp' (test . splitThese) (Just <$> occs)
171 action `shouldThrow` (const True :: Selector EventLoopException)
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