on 5feea42 help sign in
73 lines 3.1 kB history raw
1-- | This module defines 'Requester', which indicates that an action can make
2-- requests and receive responses to them. Typically, this is used for things
3-- like a WebSocket, where it's desirable to collect many potential sources of
4-- events and send them over a single channel, then distribute the results back
5-- out efficiently to their original request sites.
6{-# LANGUAGE CPP #-}
7{-# LANGUAGE FlexibleInstances #-}
8{-# LANGUAGE FunctionalDependencies #-}
9{-# LANGUAGE MultiParamTypeClasses #-}
10{-# LANGUAGE RecursiveDo #-}
11{-# LANGUAGE TypeFamilies #-}
12{-# LANGUAGE UndecidableInstances #-}
13#ifdef USE_REFLEX_OPTIMIZER
14{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
15#endif
16module Reflex.Requester.Class
17 ( Requester (..)
18 , withRequesting
19 , requestingIdentity
20 ) where
22import Control.Monad.Identity
23import Control.Monad.Reader
24import qualified Control.Monad.State.Lazy as Lazy
25import Control.Monad.State.Strict
26import Reflex.Class
28-- | A 'Requester' action can trigger requests of type @Request m a@ based on
29-- 'Event's, and receive responses of type @Response m a@ in return. Note that
30-- the @a@ type can vary within the 'Requester' action, but will be linked for a
31-- given request. For example, if @Request m@ is 'IO' and @Response m@ is
32-- 'Identity', then 'requestingIdentity' has the same type as
33-- 'Reflex.PerformEvent.Class.performEvent'.
34class (Reflex t, Monad m) => Requester t m | m -> t where
35 -- | The type of requests that this 'Requester' can emit
36 type Request m :: * -> *
37 -- | The type of responses that this 'Requester' can receive
38 type Response m :: * -> *
39 -- | Emit a request whenever the given 'Event' fires, and return responses in
40 -- the resulting 'Event'.
41 requesting :: Event t (Request m a) -> m (Event t (Response m a))
42 -- | Emit a request whenever the given 'Event' fires, and ignore all responses.
43 requesting_ :: Event t (Request m a) -> m ()
46instance Requester t m => Requester t (ReaderT r m) where
47 type Request (ReaderT r m) = Request m
48 type Response (ReaderT r m) = Response m
49 requesting = lift . requesting
50 requesting_ = lift . requesting_
52instance Requester t m => Requester t (StateT s m) where
53 type Request (StateT s m) = Request m
54 type Response (StateT s m) = Response m
55 requesting = lift . requesting
56 requesting_ = lift . requesting_
58instance Requester t m => Requester t (Lazy.StateT s m) where
59 type Request (Lazy.StateT s m) = Request m
60 type Response (Lazy.StateT s m) = Response m
61 requesting = lift . requesting
62 requesting_ = lift . requesting_
64-- | Emit a request whenever the given 'Event' fires, and unwrap the responses
65-- before returning them. @Response m@ must be 'Identity'.
66requestingIdentity :: (Requester t m, Response m ~ Identity) => Event t (Request m a) -> m (Event t a)
67requestingIdentity = fmap coerceEvent . requesting
69withRequesting :: (Requester t m, MonadFix m) => (Event t (Response m a) -> m (Event t (Request m a), r)) -> m r
70withRequesting f = do
71 rec response <- requesting request
72 (request, result) <- f response
73 return result