packages feed

reflex-transformers 0.1 → 0.2

raw patch · 7 files changed

+103/−47 lines, 7 files

Files

reflex-transformers.cabal view
@@ -1,5 +1,5 @@ name:          reflex-transformers-version:       0.1+version:       0.2 license:       BSD3 license-file:  LICENSE cabal-version: >= 1.10
src/Reflex/Monad.hs view
@@ -9,21 +9,21 @@ module Reflex.Monad    ( module Reflex.Monad.Class   -  , holdM+  , widgetHold   -  , collectMapM-  , collectM+  , mapView   +  , collection   , collect   -  , Flow (..)-  , flowM+  , Workflow (..)+  , workflow      , Chain (..)-  , chainM+  , chain   , (>->)   -  , loopM+  , loop      ) where @@ -46,9 +46,11 @@     --holdM :: (MonadSwitch t m) => m a -> Event t (m a) -> m (Dynamic t a)-holdM initial e = holdDyn' =<< switchM (Updated initial e)+-- | Hold a monadic widget and update it whenever the Event provides a new+-- monadic widget, swapping out the previously active widget.+-- Returns a Dynamic giving the return values of widgets created+widgetHold :: (MonadSwitch t m) => m a -> Event t (m a) -> m (Dynamic t a)+widgetHold initial e = holdDyn' =<< switchM (Updated initial e)   withIds :: (MonadReflex t m) => [a] -> Event t [a] -> m (Map Int a, Event t (Map Int a))@@ -59,13 +61,18 @@       zipFrom n = Map.fromList . zip [n..]       -+-- | Non monadic version of collection, builds a collection from an initial list and a list of updated values+-- items remove themselves upon the event triggering.+-- returns an UpdatedMap with keys assigned to items in ascending order collect :: (MonadReflex t m) => [(a, Event t ())] -> Event t [(a, Event t ())] -> m (UpdatedMap t Int a)-collect initial added = runReflexM $ collectM (pure <$> initial)  (fmap pure <$> added)-    +collect initial added = runReflexM $ collection (pure <$> initial)  (fmap pure <$> added)     -collectM :: (MonadSwitch t m) => [m (a, Event t ())] -> Event t [m (a, Event t ())] -> m (UpdatedMap t Int a)-collectM initial added = do ++-- | Builds a collection of widgets from an initial list and events providing new widgets to create+-- as with collect, items remove themselves upon the event triggering.    +-- returns an UpdatedMap with keys assigned to items in ascending order+collection :: (MonadSwitch t m) => [m (a, Event t ())] -> Event t [m (a, Event t ())] -> m (UpdatedMap t Int a)+collection initial added = do    (initialMap, addedMap) <- withIds initial added   rec     @@ -81,9 +88,11 @@         +-- | Provides a view into a Dynamic Map value, where sub-views are created using a function passed in+-- returns a Dynamic Map of values returned from child views upon creation. -collectMapM :: (MonadSwitch t m, Ord k) => Dynamic t (Map k v) -> (k -> Dynamic t v ->  m a) ->  m (Dynamic t (Map k a))-collectMapM input childView =  do+mapView :: (MonadSwitch t m, Ord k) => Dynamic t (Map k v) -> (k -> Dynamic t v ->  m a) ->  m (Dynamic t (Map k a))+mapView input childView =  do   inputViews <- mapDyn (Map.mapWithKey itemView) input   let updates = shallowDiff (current inputViews) (updated inputViews)   @@ -94,30 +103,47 @@     itemView k v = holdDyn v (fmapMaybe (Map.lookup k) (updated input)) >>= childView k            -newtype Flow t m a = Flow { unFlow :: m (a, Event t (Flow t m a)) }+     -flowM :: (MonadSwitch t m) => Flow t m a -> m (Dynamic t a)-flowM (Flow w) = do+-- | Recursive Workflow datatype, see 'workflow' below++newtype Workflow t m a = Workflow { unFlow :: m (a, Event t (Workflow t m a)) }+++-- | Provide a widget which swaps itself out for another widget upon an event+-- (recursively)+-- Useful if the sequence of widgets needs to return a value (as opposed to passing it +-- down the chain).++workflow :: (MonadSwitch t m) => Workflow t m a -> m (Dynamic t a)+workflow (Workflow w) = do   rec -    result <- holdM w $ unFlow <$> switch (snd <$> current result)+    result <- widgetHold w $ unFlow <$> switch (snd <$> current result)   mapDyn fst result                   -chainM :: (MonadSwitch t m) => Chain t m a b -> a -> m (Event t b)-chainM c a = switchPromptlyDyn <$> flowM (toFlow c a)+-- | Provide a way of chaining widgets of type (a -> m (Event t b))+-- where one widgets swaps out the old widget.+-- De-couples the return type as compared to using 'workflow' +chain :: (MonadSwitch t m) => Chain t m a b -> a -> m (Event t b)+chain c a = switchPromptlyDyn <$> workflow (toFlow c a) -loopM :: (MonadSwitch t m) => (a -> m (Event t a)) -> a -> m (Event t a)-loopM f a = do++-- | Provide a way of looping (a -> m (Event t a)), each iteration switches+-- out the previous iteration.+-- Can be used with +loop :: (MonadSwitch t m) => (a -> m (Event t a)) -> a -> m (Event t a)+loop f a = do   rec-    e <- switchPromptlyDyn <$> holdM (f a) (f <$> e)+    e <- switchPromptlyDyn <$> widgetHold (f a) (f <$> e)        return e   -  +-- | Data type wrapping chainable widgets of the type (a -> m (Event t a))  data Chain t m a b where     Chain :: (a -> m (Event t b)) -> Chain t m a b     (:>>) ::  (a -> m (Event t b)) -> Chain t m b c ->  Chain t m a c@@ -127,17 +153,20 @@ infixr 8 :>>    +-- | Compose two 'Chain' values passing the output event of one +-- into the construction function of the next.+ (>->) :: Chain t m a b -> Chain t m b c -> Chain t m a c   Chain f    >-> c  =  f :>> c  (f :>> c') >-> c  =  f :>> (c' >-> c)  -toFlow :: (MonadSwitch t m) => Chain t m a b -> a -> Flow t m (Event t b)-toFlow (Chain f) a = Flow $ do +toFlow :: (MonadSwitch t m) => Chain t m a b -> a -> Workflow t m (Event t b)+toFlow (Chain f) a = Workflow $ do    e <- f a    return (e, end <$ e)-    where end = Flow $ return (never, never)+    where end = Workflow $ return (never, never)     -toFlow (f :>> c) a = Flow $ do+toFlow (f :>> c) a = Workflow $ do   e <- f a   return (never, toFlow c <$> e)   
src/Reflex/Monad/Class.hs view
@@ -36,26 +36,26 @@ import Prelude  --- Constraint type to capture common usage together+-- | Constraint type to capture common usage together type MonadReflex t m = (Reflex t, MonadHold t m, MonadFix m)           class (MonadReflex t m) => MonadSwitch t m | m -> t where   -  -- | Map the result of an initial monadic action and updates and swap -  -- it out with a new one whenever the event provided fires.-  -- returns an 'Updated' giving the initial value plus updates-  -- +    -- | Map the result of an initial monadic action and updates and swap +    -- it out with a new one whenever the event provided fires.+    -- returns an Updated giving the initial value plus updates+       switchM ::  Updated t (m a) -> m (Updated t a)     switchM u = do        m <- switchMapM (toMap (Just <$> u))       return $ fromJust <$> fromMap m              -  -- | Similar to holdM but operating on a collection of widgets-  -- provided as an 'UpdatedMap'.-  -- switchM/switchM' can be implemented in terms of switchMapM -  -- therefore switchMapM is a minimal implementation.+    -- | Similar to holdM but operating on a collection of widgets+    -- provided as an 'UpdatedMap'.+    -- switchM/switchM' can be implemented in terms of switchMapM +    -- therefore switchMapM is a minimal implementation.     switchMapM ::  Ord k => UpdatedMap t k (m a) -> m (UpdatedMap t k a)          @@ -88,7 +88,7 @@         - -- | A few conversions for switchM in terms of switchMapM+-- A few conversions for switchM in terms of switchMapM maybeToMap :: Maybe a -> Map () a maybeToMap Nothing  = mempty maybeToMap (Just a) = Map.singleton () a
src/Reflex/Monad/ReaderWriter.hs view
@@ -28,7 +28,14 @@  import Prelude -    ++-- | Fusion between ReaderT and WriterT (But not StateT unlike RWST) +-- which is switchable using MonadSwitch+--+-- Uses implementation based on RSST which implements WriterT using state+-- in order to avoid space leaks incurred by the original WriterT+--  +   newtype ReaderWriterT r w m a = ReaderWriterT (RSST r w () m a)   deriving (Functor, Applicative, Monad, MonadTrans, MonadFix, MonadReader r, MonadWriter w)   @@ -55,7 +62,7 @@   return (a, w)    -execReaderWriterT :: (Monad m, Monoid w) => ReaderWriterT r w m a -> r -> m w+execReaderWriterT :: (Functor m, Monad m, Monoid w) => ReaderWriterT r w m a -> r -> m w execReaderWriterT m r = snd <$> runReaderWriterT m r      
src/Reflex/Monad/ReflexM.hs view
@@ -10,6 +10,8 @@  import Prelude +-- | Base Monad which sits at the bottom of a (pure) switching Monad transformer stack providing+-- the base switching capabilities.  newtype ReflexM t a = ReflexM { runReflexM :: forall m. MonadReflex t m => m a } 
src/Reflex/Switching.hs view
@@ -1,6 +1,12 @@ {-# LANGUAGE UndecidableInstances #-} -module Reflex.Switching where+module Reflex.Switching +  ( Switching (..)+  , SwitchMerge (..)+  , switching'+  , switchMerge'+  +  ) where   import Reflex.Class hiding (constant)@@ -24,6 +30,7 @@    switching :: MonadHold t m => r -> Event t r -> m r     class (Switching t r, Monoid r) => SwitchMerge t r  where   +   -- | Switching for a changing collections of reactive types    switchMerge :: (MonadFix m, MonadHold t m, Ord k) => Map k r -> Event t (Map k (Maybe r)) -> m r  @@ -82,9 +89,13 @@ instance (Reflex t) => Switching t () where   switching _ _ = pure ()   +  +-- | Helper which takes an UpdatedMap as one argument (instead of initial value, update event separately) switchMerge' :: (Reflex t, SwitchMerge t r, MonadFix m, MonadHold t m, Ord k) => UpdatedMap t k r -> m r  switchMerge' (UpdatedMap initial e) = switchMerge initial e   ++-- | Helper which takes an Updated as one argument (instead of initial value, update event separately) switching' :: (Reflex t, Switching t r, MonadFix m, MonadHold t m) => Updated t r -> m r  switching' (Updated initial e) = switching initial e   
src/Reflex/Updated.hs view
@@ -25,9 +25,10 @@  import Prelude  -+-- | Data type for a collection (a map) which is updated by providing differences data UpdatedMap t k a = UpdatedMap (Map k a) (Event t (Map k (Maybe a)))    +-- | Data type for an initial value which is updated, mainly useful for it's Functor instance data Updated t a = Updated a (Event t a)  @@ -42,11 +43,12 @@ instance Reflex t => FunctorWithIndex k (UpdatedMap t k) where   imap f (UpdatedMap initial changes) = UpdatedMap (imap f initial) (imap (fmap . f) <$> changes) -+-- | Generalized unzip - probably not the best place for this! split :: Functor f => f (a, b) -> (f a, f b) split f = (fst <$> f, snd <$> f)  +-- | Turn an UpdatedMap into a Dynamic by applying the differences to the initial value holdMapDyn :: (Reflex t, MonadHold t m, MonadFix m, Ord k) => UpdatedMap t k a -> m (Dynamic t (Map k a)) holdMapDyn (UpdatedMap initial changes) = foldDyn (flip (ifoldr modify)) initial changes   @@ -55,21 +57,26 @@     modify k (Just item) items = Map.insert k item items          +-- | Hold an UpdatedMap as a behavior by applying differences to the initial value holdMap :: (Reflex t, MonadHold t m, MonadFix m, Ord k) => UpdatedMap t k a -> m (Behavior t (Map k a)) holdMap = (current <$>) . holdMapDyn       +-- | Hold an 'Updated' as a Dynamic by replacing the initial value with updates holdDyn' :: (Reflex t, MonadHold t m, MonadFix m) => Updated t a -> m (Dynamic t a)     holdDyn' (Updated initial changes) = holdDyn initial changes +-- | Hold an 'Updated' as a Behavior by replacing the initial value with updates hold' :: (Reflex t, MonadHold t m, MonadFix m) => Updated t a -> m (Behavior t a)     hold' (Updated initial changes) = hold initial changes                  +-- | Find the shallow (structural) differences between two Maps         shallowDiff' :: (Ord k) => Map k a -> Map k b -> Map k (Maybe b) shallowDiff' m m' = (Just <$> m' Map.\\ m)  <> (const Nothing <$>  m Map.\\ m')                   +-- | Track the shallow (structural) differences between a Behavior and an Event      shallowDiff :: (Reflex t, Ord k) => Behavior t (Map k a) -> Event t (Map k b) -> Event t (Map k (Maybe b)) shallowDiff currentItems updatedItems = ffilter (not . Map.null) $    attachWith shallowDiff' currentItems updatedItems