packages feed

reflex 0.8.1.1 → 0.8.2.0

raw patch · 3 files changed

+97/−27 lines, 3 filesdep ~basedep ~constraintsdep ~lensPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: base, constraints, lens, random, ref-tf, semialign, template-haskell, these, witherable

API changes (from Hackage documentation)

- Data.FastMutableIntMap: [unPatchIntMap] :: PatchIntMap a -> IntMap (Maybe a)
- Reflex.Class: data EitherTag (l :: k) (r :: k) (a :: k)
- Reflex.Class: instance forall k (t :: k). Reflex.Class.Reflex t => Data.Semialign.Internal.Unzip (Reflex.Class.Event t)
- Reflex.Class: instance forall k (t :: k). Reflex.Class.Reflex t => Data.Semialign.Internal.Zip (Reflex.Class.Event t)
- Reflex.Class: instance forall k (t :: k). Reflex.Class.Reflex t => Data.Witherable.Class.Filterable (Reflex.Class.Event t)
- Reflex.Dynamic: instance (l' GHC.Types.~ Reflex.Dynamic.HRevApp l '[]) => Reflex.Dynamic.HBuild' l (Reflex.Dynamic.HList l')
- Reflex.Dynamic: instance forall k (l :: [k]). Data.GADT.Internal.GCompare (Reflex.Dynamic.HListPtr l)
- Reflex.Dynamic: instance forall k (l :: [k]). Data.GADT.Internal.GEq (Reflex.Dynamic.HListPtr l)
- Reflex.EventWriter.Base: instance Data.GADT.Internal.GCompare (Reflex.EventWriter.Base.TellId w)
- Reflex.EventWriter.Base: instance Data.GADT.Internal.GEq (Reflex.EventWriter.Base.TellId w)
- Reflex.PerformEvent.Base: instance (Reflex.Host.Class.ReflexHost t, Control.Monad.Ref.Ref m GHC.Types.~ Control.Monad.Ref.Ref GHC.Types.IO) => Reflex.PerformEvent.Class.PerformEvent t (Reflex.PerformEvent.Base.PerformEventT t m)
- Reflex.Query.Class: instance GHC.Ix.Ix Reflex.Query.Class.SelectedCount
- Reflex.Requester.Base: instance Data.GADT.Internal.GCompare (Reflex.Requester.Base.MyTagWrap f)
- Reflex.Requester.Base: instance Data.GADT.Internal.GCompare Reflex.Requester.Base.MyTag
- Reflex.Requester.Base: instance Data.GADT.Internal.GEq (Reflex.Requester.Base.MyTagWrap f)
- Reflex.Requester.Base: instance Data.GADT.Internal.GEq Reflex.Requester.Base.MyTag
- Reflex.Spider.Internal: instance Data.GADT.Internal.GEq Reflex.Spider.Internal.SpiderTimelineEnv
- Reflex.Spider.Internal: instance Reflex.Spider.Internal.HasSpiderTimeline x => Data.Semialign.Internal.Zip (Reflex.Spider.Internal.Event x)
- Reflex.Spider.Internal: instance Reflex.Spider.Internal.HasSpiderTimeline x => Data.Witherable.Class.Filterable (Reflex.Spider.Internal.Event x)
- Reflex.Spider.Internal: instance Reflex.Spider.Internal.HasSpiderTimeline x => Reflex.Spider.Internal.Defer (Data.Some.Newtype.Some Reflex.Spider.Internal.Clear) (Reflex.Spider.Internal.EventM x)
- Reflex.Spider.Internal: instance Reflex.Spider.Internal.HasSpiderTimeline x => Reflex.Spider.Internal.Defer (Data.Some.Newtype.Some Reflex.Spider.Internal.IntClear) (Reflex.Spider.Internal.EventM x)
- Reflex.Spider.Internal: instance Reflex.Spider.Internal.HasSpiderTimeline x => Reflex.Spider.Internal.Defer (Data.Some.Newtype.Some Reflex.Spider.Internal.RootClear) (Reflex.Spider.Internal.EventM x)
- Reflex.TriggerEvent.Base: instance (GHC.Base.Monad m, Control.Monad.Ref.MonadRef m, Control.Monad.Ref.Ref m GHC.Types.~ Control.Monad.Ref.Ref GHC.Types.IO, Reflex.Host.Class.MonadReflexCreateTrigger t m) => Reflex.TriggerEvent.Class.TriggerEvent t (Reflex.TriggerEvent.Base.TriggerEventT t m)
+ Data.AppendMap: instance Data.Witherable.Filterable (Data.Map.Monoidal.MonoidalMap k)
+ Reflex.Class: data EitherTag (l :: k) (r :: k) (a :: k) :: forall k. () => k -> k -> k -> Type
+ Reflex.Class: instance forall k (t :: k). Reflex.Class.Reflex t => Data.Witherable.Filterable (Reflex.Class.Event t)
+ Reflex.Dynamic: instance (l' Data.Type.Equality.~ Reflex.Dynamic.HRevApp l '[]) => Reflex.Dynamic.HBuild' l (Reflex.Dynamic.HList l')
+ Reflex.Dynamic: instance forall k (l :: [k]). Data.GADT.Compare.GCompare (Reflex.Dynamic.HListPtr l)
+ Reflex.Dynamic: instance forall k (l :: [k]). Data.GADT.Compare.GEq (Reflex.Dynamic.HListPtr l)
+ Reflex.EventWriter.Base: instance Data.GADT.Compare.GCompare (Reflex.EventWriter.Base.TellId w)
+ Reflex.EventWriter.Base: instance Data.GADT.Compare.GEq (Reflex.EventWriter.Base.TellId w)
+ Reflex.PerformEvent.Base: instance (Reflex.Host.Class.ReflexHost t, Control.Monad.Ref.Ref m Data.Type.Equality.~ Control.Monad.Ref.Ref GHC.Types.IO) => Reflex.PerformEvent.Class.PerformEvent t (Reflex.PerformEvent.Base.PerformEventT t m)
+ Reflex.Query.Class: instance GHC.Arr.Ix Reflex.Query.Class.SelectedCount
+ Reflex.Requester.Base: instance Data.GADT.Compare.GCompare (Reflex.Requester.Base.MyTagWrap f)
+ Reflex.Requester.Base: instance Data.GADT.Compare.GCompare Reflex.Requester.Base.MyTag
+ Reflex.Requester.Base: instance Data.GADT.Compare.GEq (Reflex.Requester.Base.MyTagWrap f)
+ Reflex.Requester.Base: instance Data.GADT.Compare.GEq Reflex.Requester.Base.MyTag
+ Reflex.Requester.Base: matchResponseMapWithRequests :: forall t rawRequest rawResponse request response m. (MonadFix m, MonadHold t m, Reflex t) => (forall a. request a -> (rawRequest, rawResponse -> response a)) -> Event t (RequesterData request) -> Event t (Map Int rawResponse) -> m (Event t (Map Int rawRequest), Event t (RequesterData response))
+ Reflex.Spider.Internal: instance Data.GADT.Compare.GEq Reflex.Spider.Internal.SpiderTimelineEnv
+ Reflex.Spider.Internal: instance Reflex.Spider.Internal.HasSpiderTimeline x => Data.Witherable.Filterable (Reflex.Spider.Internal.Event x)
+ Reflex.Spider.Internal: instance Reflex.Spider.Internal.HasSpiderTimeline x => Reflex.Spider.Internal.Defer (Data.Some.Some Reflex.Spider.Internal.Clear) (Reflex.Spider.Internal.EventM x)
+ Reflex.Spider.Internal: instance Reflex.Spider.Internal.HasSpiderTimeline x => Reflex.Spider.Internal.Defer (Data.Some.Some Reflex.Spider.Internal.IntClear) (Reflex.Spider.Internal.EventM x)
+ Reflex.Spider.Internal: instance Reflex.Spider.Internal.HasSpiderTimeline x => Reflex.Spider.Internal.Defer (Data.Some.Some Reflex.Spider.Internal.RootClear) (Reflex.Spider.Internal.EventM x)
+ Reflex.TriggerEvent.Base: instance (GHC.Base.Monad m, Control.Monad.Ref.MonadRef m, Control.Monad.Ref.Ref m Data.Type.Equality.~ Control.Monad.Ref.Ref GHC.Types.IO, Reflex.Host.Class.MonadReflexCreateTrigger t m) => Reflex.TriggerEvent.Class.TriggerEvent t (Reflex.TriggerEvent.Base.TriggerEventT t m)
- Data.FastMutableIntMap: getDeletions :: PatchIntMap v -> IntMap v' -> IntMap v'
+ Data.FastMutableIntMap: getDeletions :: () => PatchIntMap v -> IntMap v' -> IntMap v'
- Data.FastMutableIntMap: patchIntMapNewElements :: PatchIntMap a -> [a]
+ Data.FastMutableIntMap: patchIntMapNewElements :: () => PatchIntMap a -> [a]
- Data.FastMutableIntMap: patchIntMapNewElementsMap :: PatchIntMap a -> IntMap a
+ Data.FastMutableIntMap: patchIntMapNewElementsMap :: () => PatchIntMap a -> IntMap a
- Reflex.Class: [LeftTag] :: forall k (l :: k) (r :: k). EitherTag l r l
+ Reflex.Class: [LeftTag] :: forall k (l :: k) (r :: k) (a :: k). () => EitherTag l r l
- Reflex.Class: [RightTag] :: forall k (l :: k) (r :: k). EitherTag l r r
+ Reflex.Class: [RightTag] :: forall k (l :: k) (r :: k) (a :: k). () => EitherTag l r r
- Reflex.Class: dmapToThese :: DMap (EitherTag a b) Identity -> Maybe (These a b)
+ Reflex.Class: dmapToThese :: () => DMap (EitherTag a b) Identity -> Maybe (These a b)
- Reflex.Class: dsumToEither :: DSum (EitherTag a b) Identity -> Either a b
+ Reflex.Class: dsumToEither :: () => DSum (EitherTag a b) Identity -> Either a b
- Reflex.Class: eitherToDSum :: Either a b -> DSum (EitherTag a b) Identity
+ Reflex.Class: eitherToDSum :: () => Either a b -> DSum (EitherTag a b) Identity
- Reflex.Requester.Base: RequesterT :: StateT (RequesterState t request) (ReaderT (EventSelectorInt t Any) m) a -> RequesterT t request (response :: * -> *) m a
+ Reflex.Requester.Base: RequesterT :: StateT (RequesterState t request) (ReaderT (EventSelectorInt t Any) m) a -> RequesterT t request m a
- Reflex.Requester.Base: [unRequesterT] :: RequesterT t request (response :: * -> *) m a -> StateT (RequesterState t request) (ReaderT (EventSelectorInt t Any) m) a
+ Reflex.Requester.Base: [unRequesterT] :: RequesterT t request m a -> StateT (RequesterState t request) (ReaderT (EventSelectorInt t Any) m) a
- Reflex.Spider.Internal: Dyn :: IORef (DynType x p) -> Dyn (x :: Type) p
+ Reflex.Spider.Internal: Dyn :: IORef (DynType x p) -> Dyn p
- Reflex.Spider.Internal: SpiderHost :: IO a -> SpiderHost (x :: Type) a
+ Reflex.Spider.Internal: SpiderHost :: IO a -> SpiderHost a
- Reflex.Spider.Internal: SpiderHostFrame :: EventM x a -> SpiderHostFrame (x :: Type) a
+ Reflex.Spider.Internal: SpiderHostFrame :: EventM x a -> SpiderHostFrame a
- Reflex.Spider.Internal: SpiderPullM :: BehaviorM x a -> SpiderPullM (x :: Type) a
+ Reflex.Spider.Internal: SpiderPullM :: BehaviorM x a -> SpiderPullM a
- Reflex.Spider.Internal: SpiderPushM :: ComputeM x a -> SpiderPushM (x :: Type) a
+ Reflex.Spider.Internal: SpiderPushM :: ComputeM x a -> SpiderPushM a
- Reflex.Spider.Internal: [runSpiderHostFrame] :: SpiderHostFrame (x :: Type) a -> EventM x a
+ Reflex.Spider.Internal: [runSpiderHostFrame] :: SpiderHostFrame a -> EventM x a
- Reflex.Spider.Internal: [unDyn] :: Dyn (x :: Type) p -> IORef (DynType x p)
+ Reflex.Spider.Internal: [unDyn] :: Dyn p -> IORef (DynType x p)
- Reflex.Spider.Internal: [unSpiderHost] :: SpiderHost (x :: Type) a -> IO a
+ Reflex.Spider.Internal: [unSpiderHost] :: SpiderHost a -> IO a

Files

ChangeLog.md view
@@ -1,5 +1,9 @@ # Revision history for reflex +## 0.8.2.0++* Add `matchResponseMapWithRequests`, which it similar to `matchResponsesWithRequests` but allows processing of multiple responses at once.+ ## 0.8.1.1  * Allow newer hlint for older GHCs, and add upper bound for newer GHCs
reflex.cabal view
@@ -1,5 +1,5 @@ Name: reflex-Version: 0.8.1.1+Version: 0.8.2.0 Synopsis: Higher-order Functional Reactive Programming Description:   Interactive programs without callbacks or side-effects.@@ -74,6 +74,7 @@     base >= 4.11 && < 4.15,     bifunctors >= 5.2 && < 5.6,     comonad >= 5.0.4 && < 5.1,+    constraints >= 0.10 && <0.14,     constraints-extras >= 0.3 && < 0.4,     containers >= 0.6 && < 0.7,     data-default >= 0.5 && < 0.8,
src/Reflex/Requester/Base.hs view
@@ -1,6 +1,7 @@ -- | This module provides 'RequesterT', the standard implementation of -- 'Requester'. {-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE ApplicativeDo #-} {-# LANGUAGE CPP #-} {-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE ExistentialQuantification #-}@@ -32,6 +33,7 @@   , requesterDataToList   , singletonRequesterData   , matchResponsesWithRequests+  , matchResponseMapWithRequests   , multiEntry   , unMultiEntry   , requesting'@@ -56,6 +58,7 @@ import Control.Monad.State.Strict import Data.Bits import Data.Coerce+import Data.Constraint import Data.Dependent.Map (DMap) import qualified Data.Dependent.Map as DMap import Data.Dependent.Sum (DSum (..))@@ -81,19 +84,51 @@  newtype RequesterData f = RequesterData (TagMap (Entry f)) +emptyRequesterData :: RequesterData f+emptyRequesterData = RequesterData $ TagMap IntMap.empty+ data RequesterDataKey a where   RequesterDataKey_Single :: {-# UNPACK #-} !(MyTag (Single a)) -> RequesterDataKey a   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-  RequesterDataKey_Multi2 :: {-# UNPACK #-} !(MyTag (Multi2 k)) -> !(Some k) -> {-# UNPACK #-} !Int -> !(RequesterDataKey a) -> RequesterDataKey a+  RequesterDataKey_Multi2 :: GCompare k => {-# UNPACK #-} !(MyTag (Multi2 k)) -> !(Some k) -> {-# UNPACK #-} !Int -> !(RequesterDataKey a) -> RequesterDataKey a   RequesterDataKey_Multi3 :: {-# UNPACK #-} !(MyTag Multi3) -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> !(RequesterDataKey a) -> RequesterDataKey a  singletonRequesterData :: RequesterDataKey a -> f a -> RequesterData f singletonRequesterData rdk v = case rdk of   RequesterDataKey_Single k -> RequesterData $ singletonTagMap k $ Entry v   RequesterDataKey_Multi k k' k'' -> RequesterData $ singletonTagMap k $ Entry $ IntMap.singleton k' $ singletonRequesterData k'' v-  RequesterDataKey_Multi2 k k' k'' k''' -> RequesterData $ singletonTagMap k $ Entry $ Map.singleton k' $ IntMap.singleton k'' $ singletonRequesterData k''' v+  RequesterDataKey_Multi2 k k' k'' k''' -> RequesterData $ singletonTagMap k $ Entry $ Multi2Contents+    { _multi2Contents_values = Map.singleton k' $ IntMap.singleton k'' $ singletonRequesterData k''' v+    , _multi2Contents_dict = Dict+    }   RequesterDataKey_Multi3 k k' k'' k''' -> RequesterData $ singletonTagMap k $ Entry $ IntMap.singleton k' $ IntMap.singleton k'' $ singletonRequesterData k''' v +mergeRequesterData :: RequesterData f -> RequesterData f -> RequesterData f+mergeRequesterData (RequesterData a) (RequesterData b) = RequesterData $ mergeTagMap a b++mergeTagMap :: forall f. TagMap (Entry f) -> TagMap (Entry f) -> TagMap (Entry f)+mergeTagMap (TagMap m) (TagMap n) =+  TagMap $ IntMap.unionWithKey (g' combiner) m n+  where+    combiner :: forall a. MyTag a -> Entry f a -> Entry f a -> Entry f a+    combiner k (Entry a) (Entry b) = Entry $ case myKeyType k of+      MyTagType_Single -> a+      MyTagType_Multi -> IntMap.unionWith mergeRequesterData a b+      MyTagType_Multi2 -> case _multi2Contents_dict a of+        Dict -> Multi2Contents+          { _multi2Contents_values = Map.unionWith (IntMap.unionWith mergeRequesterData) (_multi2Contents_values a) (_multi2Contents_values b)+          , _multi2Contents_dict = Dict+          }+      MyTagType_Multi3 -> IntMap.unionWith (IntMap.unionWith mergeRequesterData) a b+    g' :: (forall a. MyTag a -> Entry f a -> Entry f a -> Entry f a) -> Int -> Any -> Any -> Any+    g' f rawKey a b =+      let k = MyTag rawKey :: MyTag a+          fromAny :: Any -> Entry f a+          fromAny = unsafeCoerce+          toAny :: Entry f a -> Any+          toAny = unsafeCoerce+      in toAny $ f k (fromAny a) (fromAny b)+ requesterDataToList :: RequesterData f -> [DSum RequesterDataKey f] requesterDataToList (RequesterData m) = do   k :=> Entry e <- tagMapToList m@@ -103,11 +138,12 @@       (k', e') <- IntMap.toList e       k'' :=> e'' <- requesterDataToList e'       return $ RequesterDataKey_Multi k k' k'' :=> e''-    MyTagType_Multi2 -> do-      (k', e') <- Map.toList e-      (k'', e'') <- IntMap.toList e'-      k''' :=> e''' <- requesterDataToList e''-      return $ RequesterDataKey_Multi2 k k' k'' k''' :=> e'''+    MyTagType_Multi2 -> case _multi2Contents_dict e of+      Dict -> do+        (k', e') <- Map.toList $ _multi2Contents_values e+        (k'', e'') <- IntMap.toList e'+        k''' :=> e''' <- requesterDataToList e''+        return $ RequesterDataKey_Multi2 k k' k'' k''' :=> e'''     MyTagType_Multi3 -> do       (k', e') <- IntMap.toList e       (k'', e'') <- IntMap.toList e'@@ -135,7 +171,13 @@         go k (Entry request) = Entry <$> case myKeyType k of           MyTagType_Single -> f request           MyTagType_Multi -> traverse (traverseRequesterData f) request-          MyTagType_Multi2 -> traverse (traverse (traverseRequesterData f)) request+          MyTagType_Multi2 -> case request of+            Multi2Contents { _multi2Contents_values = request', _multi2Contents_dict = Dict } -> do+              v <- traverse (traverse (traverseRequesterData f)) request'+              pure $ Multi2Contents+                { _multi2Contents_values = v+                , _multi2Contents_dict = Dict+                }           MyTagType_Multi3 -> traverse (traverse (traverseRequesterData f)) request  -- | 'traverseRequesterData' with its arguments flipped@@ -179,9 +221,14 @@ type family EntryContents request a where   EntryContents request (Single a) = request a   EntryContents request Multi = IntMap (RequesterData request)-  EntryContents request (Multi2 k) = Map (Some k) (IntMap (RequesterData request))+  EntryContents request (Multi2 k) = Multi2Contents k request   EntryContents request Multi3 = IntMap (IntMap (RequesterData request)) +data Multi2Contents k request = Multi2Contents+  { _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+  , _multi2Contents_values :: {-# UNPACK #-} !(Map (Some k) (IntMap (RequesterData request)))+  }+ newtype Entry request x = Entry { unEntry :: EntryContents request x }  {-# INLINE singleEntry #-}@@ -310,7 +357,7 @@   return t  {-# INLINE responseFromTag #-}-responseFromTag :: Monad m => MyTagWrap response (Entry response x) -> RequesterT t request response m (Event t (Entry response x))+responseFromTag :: forall m t request response x. Monad m => MyTagWrap response (Entry response x) -> RequesterT t request response m (Event t (Entry response x)) responseFromTag (MyTagWrap t) = do   responses :: EventSelectorInt t Any <- RequesterT ask   return $ (unsafeCoerce :: Event t Any -> Event t (Entry response x)) $ selectInt responses t@@ -440,9 +487,9 @@       let responses :: EventSelector t (Const2 (Some k) (IntMap (RequesterData response)))           responses = fanMap $ fmapCheap unpack response           unpack :: Entry response (Multi2 k) -> Map (Some k) (IntMap (RequesterData response))-          unpack = unEntry+          unpack = _multi2Contents_values . unEntry           pack :: Map (Some k) (IntMap (RequesterData request)) -> Entry request (Multi2 k)-          pack = Entry+          pack m = Entry $ Multi2Contents { _multi2Contents_values = m, _multi2Contents_dict = Dict }           f' :: forall a. k a -> Compose ((,) Int) v a -> m (Compose ((,) (Event t (IntMap (RequesterData request)))) v' a)           f' k (Compose (n, v)) = do             (result, myRequests) <- runRequesterT (f k v) $ mapMaybeCheap (IntMap.lookup n) $ select responses (Const2 (Some k))@@ -463,9 +510,6 @@ data Decoder rawResponse response =   forall a. Decoder (RequesterDataKey a) (rawResponse -> response a) --- | Matches incoming responses with previously-sent requests--- and uses the provided request "decoder" function to process--- incoming responses. matchResponsesWithRequests   :: forall t rawRequest rawResponse request response m.      ( MonadFix m@@ -484,7 +528,30 @@        )   -- ^ A map of outgoing wire-format requests and an event of responses keyed   -- by the 'RequesterData' key of the associated outgoing request-matchResponsesWithRequests f send recv = do+matchResponsesWithRequests f send recv = matchResponseMapWithRequests f send $ uncurry Map.singleton <$> recv++-- | Matches incoming responses with previously-sent requests+-- and uses the provided request "decoder" function to process+-- incoming responses.+matchResponseMapWithRequests+  :: forall t rawRequest rawResponse request response m.+     ( MonadFix m+     , MonadHold t m+     , Reflex t+     )+  => (forall a. request a -> (rawRequest, rawResponse -> response a))+  -- ^ Given a request (from 'Requester'), produces the wire format of the+  -- request and a function used to process the associated response+  -> Event t (RequesterData request)+  -- ^ The outgoing requests+  -> Event t (Map Int rawResponse)+  -- ^ A map of incoming responses, tagged by an identifying key+  -> m ( Event t (Map Int rawRequest)+       , Event t (RequesterData response)+       )+  -- ^ A map of outgoing wire-format requests and an event of responses keyed+  -- by the 'RequesterData' key of the associated outgoing request+matchResponseMapWithRequests f send recv = do   rec nextId <- hold 1 $ fmap (\(next, _, _) -> next) outgoing       waitingFor :: Incremental t (PatchMap Int (Decoder rawResponse response)) <-         holdIncremental mempty $ leftmost@@ -526,17 +593,15 @@     processIncoming       :: Incremental t (PatchMap Int (Decoder rawResponse response))       -- A map of outstanding expected responses-      -> Event t (Int, rawResponse)+      -> Event t (Map Int rawResponse)       -- A incoming response paired with its identifying key       -> Event t (RequesterData response, PatchMap Int v)       -- The decoded response and a patch that clears the outstanding responses queue-    processIncoming waitingFor inc = flip push inc $ \(n, rawRsp) -> do+    processIncoming waitingFor inc = flip push inc $ \rspMap -> do       wf <- sample $ currentIncremental waitingFor-      case Map.lookup n wf of-        Nothing -> return Nothing -- TODO How should lookup failures be handled here? They shouldn't ever happen..-        Just (Decoder k rspF) -> do-          let rsp = rspF rawRsp-          return $ Just-            ( singletonRequesterData k rsp-            , PatchMap $ Map.singleton n Nothing-            )+      let match rawRsp (Decoder k rspF) =+            let rsp = rspF rawRsp+            in singletonRequesterData k rsp+          matches = Map.intersectionWith match rspMap wf+      pure $ if Map.null matches then Nothing else Just+        (Map.foldl' mergeRequesterData emptyRequesterData matches, PatchMap $ Nothing <$ matches)