on 4f69eca help sign in
.github/workflows/haskell.yml+7−3
since splitsnapshots
unifiedsplit
@@ -1,6 +1,6 @@
1name: github-action
1name: github-action
2
2
3−on: [push, pull_request]
3+on: [push, pull_request]
4
4
5jobs:
5jobs:
6 build:
6 build:
@@ -8,6 +8,12 @@ jobs:
8 matrix:
8 matrix:
9 ghc: ['8.4.4', '8.6.5', '8.8.4', '8.10.2']
9 ghc: ['8.4.4', '8.6.5', '8.8.4', '8.10.2']
10 os: ['ubuntu-latest', 'macos-latest']
10 os: ['ubuntu-latest', 'macos-latest']
11+ exclude:
12+ # There are some linker warnings in 802 on darwin that
13+ # cause compilation to fail
14+ # See https://github.com/NixOS/nixpkgs/issues/25139
15+ - ghc: '8.0.2'
16+ os: 'macos-latest'
11 runs-on: ${{ matrix.os }}
17 runs-on: ${{ matrix.os }}
12
18
13 name: GHC ${{ matrix.ghc }} on ${{ matrix.os }}
19 name: GHC ${{ matrix.ghc }} on ${{ matrix.os }}
@@ -37,5 +43,3 @@ jobs:
37 run: cabal build --enable-tests --enable-benchmarks all
43 run: cabal build --enable-tests --enable-benchmarks all
38 - name: Run tests
44 - name: Run tests
39 run: cabal test all
45 run: cabal test all
40− - name: Build Docs
41− run: cabal haddock
ChangeLog.md+2−21
@@ -1,38 +1,19 @@
1# Revision history for reflex
1# Revision history for reflex
2
2
3−## 0.8.2.0
4−
5−* Add `matchResponseMapWithRequests`, which it similar to `matchResponsesWithRequests` but allows processing of multiple responses at once.
6−
7−## 0.8.1.1
8−
9−* Allow newer hlint for older GHCs, and add upper bound for newer GHCs
10−
11## 0.8.1.0
3## 0.8.1.0
12
4
13* Add support for GHC 8.10
5* Add support for GHC 8.10
14−* Drop support for GHC < 8.4
6+* Drop support for GHC 8.2.* and earlier
15
7
16## 0.8.0.0
8## 0.8.0.0
17
9
18* Replace 0.7.2.0 with 0.8.0.0 to reflect the `MonadHold` interface change. Deprecates 0.7.2.0.
10* Replace 0.7.2.0 with 0.8.0.0 to reflect the `MonadHold` interface change. Deprecates 0.7.2.0.
19
11
20−## 0.7.2.0 -- *Deprecated*
12+## 0.7.2.0
21−
22* ([#416](https://github.com/reflex-frp/reflex/pull/416)) Add `now :: m (Event t ())` to `MonadHold`.
13* ([#416](https://github.com/reflex-frp/reflex/pull/416)) Add `now :: m (Event t ())` to `MonadHold`.
23* Extend some dependency version bounds
14* Extend some dependency version bounds
24* Fix HLint 3 test
15* Fix HLint 3 test
25
16
26−## 0.7.1.1
27−
28−*Backport release*.
29−Changes do not carry forward to 0.7.2.0.
30−
31−* Add support for GHC 8.10
32−* Drop support for GHC < 8.4
33−* Extend some dependency version bounds
34−* Fix HLint 3 test
35−
36## 0.7.1.0
17## 0.7.1.0
37
18
38* ([#413](https://github.com/reflex-frp/reflex/pull/413), [#417](https://github.com/reflex-frp/reflex/pull/417)) Add `Reflex.Host.Headless` module which provides `runHeadlessApp` as an easy way to run a Reflex network in a "headless" environment.
19* ([#413](https://github.com/reflex-frp/reflex/pull/413), [#417](https://github.com/reflex-frp/reflex/pull/417)) Add `Reflex.Host.Headless` module which provides `runHeadlessApp` as an easy way to run a Reflex network in a "headless" environment.
README.md+3−3
@@ -1,4 +1,4 @@
1−# [Reflex](https://reflex-frp.org/)
1+## [Reflex](https://reflex-frp.org/)
2
2
3[![Haskell](https://img.shields.io/badge/language-Haskell-orange.svg)](https://haskell.org) [![Hackage](https://img.shields.io/hackage/v/reflex.svg)](https://hackage.haskell.org/package/reflex) [![Hackage CI](https://matrix.hackage.haskell.org/api/v2/packages/reflex/badge)](https://matrix.hackage.haskell.org/#/package/reflex) [![BSD3 License](https://img.shields.io/badge/license-BSD3-blue.svg)](https://github.com/reflex-frp/reflex/blob/master/LICENSE)
3[![Haskell](https://img.shields.io/badge/language-Haskell-orange.svg)](https://haskell.org) [![Hackage](https://img.shields.io/hackage/v/reflex.svg)](https://hackage.haskell.org/package/reflex) [![Hackage CI](https://matrix.hackage.haskell.org/api/v2/packages/reflex/badge)](https://matrix.hackage.haskell.org/#/package/reflex) [![BSD3 License](https://img.shields.io/badge/license-BSD3-blue.svg)](https://github.com/reflex-frp/reflex/blob/master/LICENSE)
4
4
@@ -8,7 +8,7 @@ Reflex is a fully-deterministic, higher-order Functional Reactive Programming in
8
8
9**Visit https://reflex-frp.org for more information, tutorials, documentation and [examples](https://examples.reflex-frp.org/).**
9**Visit https://reflex-frp.org for more information, tutorials, documentation and [examples](https://examples.reflex-frp.org/).**
10
10
11−## Resources
11+### Resources
12
12
13* [Official Website](https://reflex-frp.org)
13* [Official Website](https://reflex-frp.org)
14* [Quick Reference](Quickref.md)
14* [Quick Reference](Quickref.md)
@@ -18,6 +18,6 @@ Reflex is a fully-deterministic, higher-order Functional Reactive Programming in
18* [/r/reflexfrp](https://www.reddit.com/r/reflexfrp)
18* [/r/reflexfrp](https://www.reddit.com/r/reflexfrp)
19* [irc.freenode.net #reflex-frp](http://webchat.freenode.net?channels=%23reflex-frp&uio=d4)
19* [irc.freenode.net #reflex-frp](http://webchat.freenode.net?channels=%23reflex-frp&uio=d4)
20
20
21−## Hacking
21+### Hacking
22
22
23From 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.
23From 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+6−7
@@ -1,5 +1,5 @@
1Name: reflex
1Name: reflex
2−Version: 0.8.2.0
2+Version: 0.8.1.0
3Synopsis: Higher-order Functional Reactive Programming
3Synopsis: Higher-order Functional Reactive Programming
4Description:
4Description:
5 Interactive programs without callbacks or side-effects.
5 Interactive programs without callbacks or side-effects.
@@ -29,7 +29,7 @@ extra-source-files:
29
29
30tested-with:
30tested-with:
31 GHC ==8.4.4 || ==8.6.5 || ==8.8.1 || ==8.10.2,
31 GHC ==8.4.4 || ==8.6.5 || ==8.8.1 || ==8.10.2,
32− GHCJS ==8.6
32+ GHCJS ==8.4
33
33
34flag use-reflex-optimizer
34flag use-reflex-optimizer
35 description: Use the GHC plugin Reflex.Optimizer on some of the modules in the package. This is still experimental.
35 description: Use the GHC plugin Reflex.Optimizer on some of the modules in the package. This is still experimental.
@@ -71,10 +71,9 @@ library
71 hs-source-dirs: src
71 hs-source-dirs: src
72 build-depends:
72 build-depends:
73 MemoTrie == 0.6.*,
73 MemoTrie == 0.6.*,
74− base >= 4.11 && < 4.15,
74+ base >= 4.9 && < 4.15,
75 bifunctors >= 5.2 && < 5.6,
75 bifunctors >= 5.2 && < 5.6,
76 comonad >= 5.0.4 && < 5.1,
76 comonad >= 5.0.4 && < 5.1,
77− constraints >= 0.10 && <0.14,
78 constraints-extras >= 0.3 && < 0.4,
77 constraints-extras >= 0.3 && < 0.4,
79 containers >= 0.6 && < 0.7,
78 containers >= 0.6 && < 0.7,
80 data-default >= 0.5 && < 0.8,
79 data-default >= 0.5 && < 0.8,
@@ -97,7 +96,7 @@ library
97 time >= 1.4 && < 1.10,
96 time >= 1.4 && < 1.10,
98 transformers >= 0.5.6.0 && < 0.6,
97 transformers >= 0.5.6.0 && < 0.6,
99 unbounded-delays >= 0.1.0.0 && < 0.2,
98 unbounded-delays >= 0.1.0.0 && < 0.2,
100− witherable >= 0.3 && < 0.5
99+ witherable >= 0.3 && < 0.4
101
100
102 if flag(split-these)
101 if flag(split-these)
103 build-depends: these >= 1 && <1.2,
102 build-depends: these >= 1 && <1.2,
@@ -259,9 +258,9 @@ test-suite hlint
259 , filepath
258 , filepath
260 , filemanip
259 , filemanip
261 if impl(ghc >= 8.8)
260 if impl(ghc >= 8.8)
262− build-depends: hlint >= 3 && < 4
261+ build-depends: hlint >= 3
263 else
262 else
264− build-depends: hlint (< 2.1 || >= 2.2.2) && < 4
263+ build-depends: hlint (< 2.1 || >= 2.2.2) && < 3
265 if impl(ghcjs)
264 if impl(ghcjs)
266 buildable: False
265 buildable: False
267
266
src/Reflex/Requester/Base.hs+26−91
@@ -1,7 +1,6 @@
1-- | This module provides 'RequesterT', the standard implementation of
1-- | This module provides 'RequesterT', the standard implementation of
2-- 'Requester'.
2-- 'Requester'.
3{-# LANGUAGE AllowAmbiguousTypes #-}
3{-# LANGUAGE AllowAmbiguousTypes #-}
4−{-# LANGUAGE ApplicativeDo #-}
5{-# LANGUAGE CPP #-}
4{-# LANGUAGE CPP #-}
6{-# LANGUAGE EmptyDataDecls #-}
5{-# LANGUAGE EmptyDataDecls #-}
7{-# LANGUAGE ExistentialQuantification #-}
6{-# LANGUAGE ExistentialQuantification #-}
@@ -33,7 +32,6 @@ module Reflex.Requester.Base
33 , requesterDataToList
32 , requesterDataToList
34 , singletonRequesterData
33 , singletonRequesterData
35 , matchResponsesWithRequests
34 , matchResponsesWithRequests
36− , matchResponseMapWithRequests
37 , multiEntry
35 , multiEntry
38 , unMultiEntry
36 , unMultiEntry
39 , requesting'
37 , requesting'
@@ -58,7 +56,6 @@ import Control.Monad.Ref
58import Control.Monad.State.Strict
56import Control.Monad.State.Strict
59import Data.Bits
57import Data.Bits
60import Data.Coerce
58import Data.Coerce
61−import Data.Constraint
62import Data.Dependent.Map (DMap)
59import Data.Dependent.Map (DMap)
63import qualified Data.Dependent.Map as DMap
60import qualified Data.Dependent.Map as DMap
64import Data.Dependent.Sum (DSum (..))
61import Data.Dependent.Sum (DSum (..))
@@ -84,51 +81,19 @@ newtype TagMap (f :: * -> *) = TagMap (IntMap Any)
84
81
85newtype RequesterData f = RequesterData (TagMap (Entry f))
82newtype RequesterData f = RequesterData (TagMap (Entry f))
86
83
87−emptyRequesterData :: RequesterData f
88−emptyRequesterData = RequesterData $ TagMap IntMap.empty
89−
90data RequesterDataKey a where
84data RequesterDataKey a where
91 RequesterDataKey_Single :: {-# UNPACK #-} !(MyTag (Single a)) -> RequesterDataKey a
85 RequesterDataKey_Single :: {-# UNPACK #-} !(MyTag (Single a)) -> RequesterDataKey a
92 RequesterDataKey_Multi :: {-# UNPACK #-} !(MyTag Multi) -> {-# UNPACK #-} !Int -> !(RequesterDataKey a) -> RequesterDataKey a --TODO: Don't put a second Int here (or in the other Multis); use a single Int instead
86 RequesterDataKey_Multi :: {-# UNPACK #-} !(MyTag Multi) -> {-# UNPACK #-} !Int -> !(RequesterDataKey a) -> RequesterDataKey a --TODO: Don't put a second Int here (or in the other Multis); use a single Int instead
93− RequesterDataKey_Multi2 :: GCompare k => {-# UNPACK #-} !(MyTag (Multi2 k)) -> !(Some k) -> {-# UNPACK #-} !Int -> !(RequesterDataKey a) -> RequesterDataKey a
87+ RequesterDataKey_Multi2 :: {-# UNPACK #-} !(MyTag (Multi2 k)) -> !(Some k) -> {-# UNPACK #-} !Int -> !(RequesterDataKey a) -> RequesterDataKey a
94 RequesterDataKey_Multi3 :: {-# UNPACK #-} !(MyTag Multi3) -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> !(RequesterDataKey a) -> RequesterDataKey a
88 RequesterDataKey_Multi3 :: {-# UNPACK #-} !(MyTag Multi3) -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> !(RequesterDataKey a) -> RequesterDataKey a
95
89
96singletonRequesterData :: RequesterDataKey a -> f a -> RequesterData f
90singletonRequesterData :: RequesterDataKey a -> f a -> RequesterData f
97singletonRequesterData rdk v = case rdk of
91singletonRequesterData rdk v = case rdk of
98 RequesterDataKey_Single k -> RequesterData $ singletonTagMap k $ Entry v
92 RequesterDataKey_Single k -> RequesterData $ singletonTagMap k $ Entry v
99 RequesterDataKey_Multi k k' k'' -> RequesterData $ singletonTagMap k $ Entry $ IntMap.singleton k' $ singletonRequesterData k'' v
93 RequesterDataKey_Multi k k' k'' -> RequesterData $ singletonTagMap k $ Entry $ IntMap.singleton k' $ singletonRequesterData k'' v
100− RequesterDataKey_Multi2 k k' k'' k''' -> RequesterData $ singletonTagMap k $ Entry $ Multi2Contents
94+ RequesterDataKey_Multi2 k k' k'' k''' -> RequesterData $ singletonTagMap k $ Entry $ Map.singleton k' $ IntMap.singleton k'' $ singletonRequesterData k''' v
101− { _multi2Contents_values = Map.singleton k' $ IntMap.singleton k'' $ singletonRequesterData k''' v
102− , _multi2Contents_dict = Dict
103− }
104 RequesterDataKey_Multi3 k k' k'' k''' -> RequesterData $ singletonTagMap k $ Entry $ IntMap.singleton k' $ IntMap.singleton k'' $ singletonRequesterData k''' v
95 RequesterDataKey_Multi3 k k' k'' k''' -> RequesterData $ singletonTagMap k $ Entry $ IntMap.singleton k' $ IntMap.singleton k'' $ singletonRequesterData k''' v
105
96
106−mergeRequesterData :: RequesterData f -> RequesterData f -> RequesterData f
107−mergeRequesterData (RequesterData a) (RequesterData b) = RequesterData $ mergeTagMap a b
108−
109−mergeTagMap :: forall f. TagMap (Entry f) -> TagMap (Entry f) -> TagMap (Entry f)
110−mergeTagMap (TagMap m) (TagMap n) =
111− TagMap $ IntMap.unionWithKey (g' combiner) m n
112− where
113− combiner :: forall a. MyTag a -> Entry f a -> Entry f a -> Entry f a
114− combiner k (Entry a) (Entry b) = Entry $ case myKeyType k of
115− MyTagType_Single -> a
116− MyTagType_Multi -> IntMap.unionWith mergeRequesterData a b
117− MyTagType_Multi2 -> case _multi2Contents_dict a of
118− Dict -> Multi2Contents
119− { _multi2Contents_values = Map.unionWith (IntMap.unionWith mergeRequesterData) (_multi2Contents_values a) (_multi2Contents_values b)
120− , _multi2Contents_dict = Dict
121− }
122− MyTagType_Multi3 -> IntMap.unionWith (IntMap.unionWith mergeRequesterData) a b
123− g' :: (forall a. MyTag a -> Entry f a -> Entry f a -> Entry f a) -> Int -> Any -> Any -> Any
124− g' f rawKey a b =
125− let k = MyTag rawKey :: MyTag a
126− fromAny :: Any -> Entry f a
127− fromAny = unsafeCoerce
128− toAny :: Entry f a -> Any
129− toAny = unsafeCoerce
130− in toAny $ f k (fromAny a) (fromAny b)
131−
132requesterDataToList :: RequesterData f -> [DSum RequesterDataKey f]
97requesterDataToList :: RequesterData f -> [DSum RequesterDataKey f]
133requesterDataToList (RequesterData m) = do
98requesterDataToList (RequesterData m) = do
134 k :=> Entry e <- tagMapToList m
99 k :=> Entry e <- tagMapToList m
@@ -138,12 +103,11 @@ requesterDataToList (RequesterData m) = do
138 (k', e') <- IntMap.toList e
103 (k', e') <- IntMap.toList e
139 k'' :=> e'' <- requesterDataToList e'
104 k'' :=> e'' <- requesterDataToList e'
140 return $ RequesterDataKey_Multi k k' k'' :=> e''
105 return $ RequesterDataKey_Multi k k' k'' :=> e''
141− MyTagType_Multi2 -> case _multi2Contents_dict e of
106+ MyTagType_Multi2 -> do
142− Dict -> do
143− (k', e') <- Map.toList $ _multi2Contents_values e
107+ (k', e') <- Map.toList e
144− (k'', e'') <- IntMap.toList e'
108+ (k'', e'') <- IntMap.toList e'
145− k''' :=> e''' <- requesterDataToList e''
109+ k''' :=> e''' <- requesterDataToList e''
146− return $ RequesterDataKey_Multi2 k k' k'' k''' :=> e'''
110+ return $ RequesterDataKey_Multi2 k k' k'' k''' :=> e'''
147 MyTagType_Multi3 -> do
111 MyTagType_Multi3 -> do
148 (k', e') <- IntMap.toList e
112 (k', e') <- IntMap.toList e
149 (k'', e'') <- IntMap.toList e'
113 (k'', e'') <- IntMap.toList e'
@@ -171,13 +135,7 @@ traverseRequesterData f (RequesterData m) = RequesterData <$> traverseTagMapWith
171 go k (Entry request) = Entry <$> case myKeyType k of
135 go k (Entry request) = Entry <$> case myKeyType k of
172 MyTagType_Single -> f request
136 MyTagType_Single -> f request
173 MyTagType_Multi -> traverse (traverseRequesterData f) request
137 MyTagType_Multi -> traverse (traverseRequesterData f) request
174− MyTagType_Multi2 -> case request of
175− Multi2Contents { _multi2Contents_values = request', _multi2Contents_dict = Dict } -> do
176− v <- traverse (traverse (traverseRequesterData f)) request'
138+ MyTagType_Multi2 -> traverse (traverse (traverseRequesterData f)) request
177− pure $ Multi2Contents
178− { _multi2Contents_values = v
179− , _multi2Contents_dict = Dict
180− }
181 MyTagType_Multi3 -> traverse (traverse (traverseRequesterData f)) request
139 MyTagType_Multi3 -> traverse (traverse (traverseRequesterData f)) request
182
140
183-- | 'traverseRequesterData' with its arguments flipped
141-- | 'traverseRequesterData' with its arguments flipped
@@ -221,14 +179,9 @@ instance MyTagTypeOffset Multi3 where
221type family EntryContents request a where
179type family EntryContents request a where
222 EntryContents request (Single a) = request a
180 EntryContents request (Single a) = request a
223 EntryContents request Multi = IntMap (RequesterData request)
181 EntryContents request Multi = IntMap (RequesterData request)
224− EntryContents request (Multi2 k) = Multi2Contents k request
182+ EntryContents request (Multi2 k) = Map (Some k) (IntMap (RequesterData request))
225 EntryContents request Multi3 = IntMap (IntMap (RequesterData request))
183 EntryContents request Multi3 = IntMap (IntMap (RequesterData request))
226
184
227−data Multi2Contents k request = Multi2Contents
228− { _multi2Contents_dict :: {-# UNPACK #-} !(Dict (GCompare k)) -- This is a Dict instead of an existential context because we only want to use it in certain circumstances
229− , _multi2Contents_values :: {-# UNPACK #-} !(Map (Some k) (IntMap (RequesterData request)))
230− }
231−
232newtype Entry request x = Entry { unEntry :: EntryContents request x }
185newtype Entry request x = Entry { unEntry :: EntryContents request x }
233
186
234{-# INLINE singleEntry #-}
187{-# INLINE singleEntry #-}
@@ -357,7 +310,7 @@ tagRequest req = do
357 return t
310 return t
358
311
359{-# INLINE responseFromTag #-}
312{-# INLINE responseFromTag #-}
360−responseFromTag :: forall m t request response x. Monad m => MyTagWrap response (Entry response x) -> RequesterT t request response m (Event t (Entry response x))
313+responseFromTag :: Monad m => MyTagWrap response (Entry response x) -> RequesterT t request response m (Event t (Entry response x))
361responseFromTag (MyTagWrap t) = do
314responseFromTag (MyTagWrap t) = do
362 responses :: EventSelectorInt t Any <- RequesterT ask
315 responses :: EventSelectorInt t Any <- RequesterT ask
363 return $ (unsafeCoerce :: Event t Any -> Event t (Entry response x)) $ selectInt responses t
316 return $ (unsafeCoerce :: Event t Any -> Event t (Entry response x)) $ selectInt responses t
@@ -487,9 +440,9 @@ traverseDMapWithKeyWithAdjustRequesterTWith base mapPatch weakenPatchWith patchN
487 let responses :: EventSelector t (Const2 (Some k) (IntMap (RequesterData response)))
440 let responses :: EventSelector t (Const2 (Some k) (IntMap (RequesterData response)))
488 responses = fanMap $ fmapCheap unpack response
441 responses = fanMap $ fmapCheap unpack response
489 unpack :: Entry response (Multi2 k) -> Map (Some k) (IntMap (RequesterData response))
442 unpack :: Entry response (Multi2 k) -> Map (Some k) (IntMap (RequesterData response))
490− unpack = _multi2Contents_values . unEntry
443+ unpack = unEntry
491 pack :: Map (Some k) (IntMap (RequesterData request)) -> Entry request (Multi2 k)
444 pack :: Map (Some k) (IntMap (RequesterData request)) -> Entry request (Multi2 k)
492− pack m = Entry $ Multi2Contents { _multi2Contents_values = m, _multi2Contents_dict = Dict }
445+ pack = Entry
493 f' :: forall a. k a -> Compose ((,) Int) v a -> m (Compose ((,) (Event t (IntMap (RequesterData request)))) v' a)
446 f' :: forall a. k a -> Compose ((,) Int) v a -> m (Compose ((,) (Event t (IntMap (RequesterData request)))) v' a)
494 f' k (Compose (n, v)) = do
447 f' k (Compose (n, v)) = do
495 (result, myRequests) <- runRequesterT (f k v) $ mapMaybeCheap (IntMap.lookup n) $ select responses (Const2 (Some k))
448 (result, myRequests) <- runRequesterT (f k v) $ mapMaybeCheap (IntMap.lookup n) $ select responses (Const2 (Some k))
@@ -510,30 +463,10 @@ traverseDMapWithKeyWithAdjustRequesterTWith base mapPatch weakenPatchWith patchN
510data Decoder rawResponse response =
463data Decoder rawResponse response =
511 forall a. Decoder (RequesterDataKey a) (rawResponse -> response a)
464 forall a. Decoder (RequesterDataKey a) (rawResponse -> response a)
512
465
513−matchResponsesWithRequests
514− :: forall t rawRequest rawResponse request response m.
515− ( MonadFix m
516− , MonadHold t m
517− , Reflex t
518− )
519− => (forall a. request a -> (rawRequest, rawResponse -> response a))
520− -- ^ Given a request (from 'Requester'), produces the wire format of the
521− -- request and a function used to process the associated response
522− -> Event t (RequesterData request)
523− -- ^ The outgoing requests
524− -> Event t (Int, rawResponse)
525− -- ^ The incoming responses, tagged by an identifying key
526− -> m ( Event t (Map Int rawRequest)
527− , Event t (RequesterData response)
528− )
529− -- ^ A map of outgoing wire-format requests and an event of responses keyed
530− -- by the 'RequesterData' key of the associated outgoing request
531−matchResponsesWithRequests f send recv = matchResponseMapWithRequests f send $ uncurry Map.singleton <$> recv
532−
533-- | Matches incoming responses with previously-sent requests
466-- | Matches incoming responses with previously-sent requests
534-- and uses the provided request "decoder" function to process
467-- and uses the provided request "decoder" function to process
535-- incoming responses.
468-- incoming responses.
536−matchResponseMapWithRequests
469+matchResponsesWithRequests
537 :: forall t rawRequest rawResponse request response m.
470 :: forall t rawRequest rawResponse request response m.
538 ( MonadFix m
471 ( MonadFix m
539 , MonadHold t m
472 , MonadHold t m
@@ -544,14 +477,14 @@ matchResponseMapWithRequests
544 -- request and a function used to process the associated response
477 -- request and a function used to process the associated response
545 -> Event t (RequesterData request)
478 -> Event t (RequesterData request)
546 -- ^ The outgoing requests
479 -- ^ The outgoing requests
547− -> Event t (Map Int rawResponse)
480+ -> Event t (Int, rawResponse)
548− -- ^ A map of incoming responses, tagged by an identifying key
481+ -- ^ The incoming responses, tagged by an identifying key
549 -> m ( Event t (Map Int rawRequest)
482 -> m ( Event t (Map Int rawRequest)
550 , Event t (RequesterData response)
483 , Event t (RequesterData response)
551 )
484 )
552 -- ^ A map of outgoing wire-format requests and an event of responses keyed
485 -- ^ A map of outgoing wire-format requests and an event of responses keyed
553 -- by the 'RequesterData' key of the associated outgoing request
486 -- by the 'RequesterData' key of the associated outgoing request
554−matchResponseMapWithRequests f send recv = do
487+matchResponsesWithRequests f send recv = do
555 rec nextId <- hold 1 $ fmap (\(next, _, _) -> next) outgoing
488 rec nextId <- hold 1 $ fmap (\(next, _, _) -> next) outgoing
556 waitingFor :: Incremental t (PatchMap Int (Decoder rawResponse response)) <-
489 waitingFor :: Incremental t (PatchMap Int (Decoder rawResponse response)) <-
557 holdIncremental mempty $ leftmost
490 holdIncremental mempty $ leftmost
@@ -593,15 +526,17 @@ matchResponseMapWithRequests f send recv = do
593 processIncoming
526 processIncoming
594 :: Incremental t (PatchMap Int (Decoder rawResponse response))
527 :: Incremental t (PatchMap Int (Decoder rawResponse response))
595 -- A map of outstanding expected responses
528 -- A map of outstanding expected responses
596− -> Event t (Map Int rawResponse)
529+ -> Event t (Int, rawResponse)
597 -- A incoming response paired with its identifying key
530 -- A incoming response paired with its identifying key
598 -> Event t (RequesterData response, PatchMap Int v)
531 -> Event t (RequesterData response, PatchMap Int v)
599 -- The decoded response and a patch that clears the outstanding responses queue
532 -- The decoded response and a patch that clears the outstanding responses queue
600− processIncoming waitingFor inc = flip push inc $ \rspMap -> do
533+ processIncoming waitingFor inc = flip push inc $ \(n, rawRsp) -> do
601 wf <- sample $ currentIncremental waitingFor
534 wf <- sample $ currentIncremental waitingFor
602− let match rawRsp (Decoder k rspF) =
535+ case Map.lookup n wf of
603− let rsp = rspF rawRsp
536+ Nothing -> return Nothing -- TODO How should lookup failures be handled here? They shouldn't ever happen..
604− in singletonRequesterData k rsp
537+ Just (Decoder k rspF) -> do
605− matches = Map.intersectionWith match rspMap wf
538+ let rsp = rspF rawRsp
606− pure $ if Map.null matches then Nothing else Just
539+ return $ Just
607− (Map.foldl' mergeRequesterData emptyRequesterData matches, PatchMap $ Nothing <$ matches)
540+ ( singletonRequesterData k rsp
541+ , PatchMap $ Map.singleton n Nothing
542+ )