{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RecursiveDo #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
#ifdef USE_REFLEX_OPTIMIZER
{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
#endif
module Reflex.Collection
(
listHoldWithKey
, listWithKey
, listWithKeyShallowDiff
, listViewWithKey
, selectViewListWithKey
, selectViewListWithKey_
, list
, simpleList
) where
#ifdef MIN_VERSION_semialign
import Prelude hiding (zip, zipWith)
#if MIN_VERSION_semialign(1,1,0)
import Data.Zip (Zip (..))
#endif
#endif
import Control.Monad.Identity
import Data.Align
import Data.Functor.Misc
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Map.Misc
import Data.These
import Reflex.Class
import Reflex.Adjustable.Class
import Reflex.Dynamic
import Reflex.PostBuild.Class
listHoldWithKey
:: forall t m k v a
. (Ord k, Adjustable t m, MonadHold t m)
=> Map k v
-> Event t (Map k (Maybe v))
-> (k -> v -> m a)
-> m (Dynamic t (Map k a))
listHoldWithKey m0 m' f = do
let dm0 = mapWithFunctorToDMap $ Map.mapWithKey f m0
dm' = fmap
(PatchDMap . mapWithFunctorToDMap . Map.mapWithKey
(\k v -> ComposeMaybe $ fmap (f k) v)
)
m'
(a0, a') <- sequenceDMapWithAdjust dm0 dm'
fmap dmapToMap . incrementalToDynamic <$> holdIncremental a0 a'
listWithKey
:: forall t k v m a
. (Ord k, Adjustable t m, PostBuild t m, MonadFix m, MonadHold t m)
=> Dynamic t (Map k v)
-> (k -> Dynamic t v -> m a)
-> m (Dynamic t (Map k a))
listWithKey vals mkChild = do
postBuild <- getPostBuild
let childValChangedSelector = fanMap $ updated vals
diffOnlyKeyChanges olds news =
flip Map.mapMaybe (align olds news) $ \case
This _ -> Just Nothing
These _ _ -> Nothing
That new -> Just $ Just new
rec sentVals :: Dynamic t (Map k v) <- foldDyn applyMap Map.empty changeVals
let changeVals :: Event t (Map k (Maybe v))
changeVals =
attachWith diffOnlyKeyChanges (current sentVals) $ leftmost
[ updated vals
, tag (current vals) postBuild
]
listHoldWithKey Map.empty changeVals $ \k v ->
mkChild k =<< holdDyn v (select childValChangedSelector $ Const2 k)
listWithKeyShallowDiff
:: (Ord k, Adjustable t m, MonadFix m, MonadHold t m)
=> Map k v
-> Event t (Map k (Maybe v))
-> (k -> v -> Event t v -> m a)
-> m (Dynamic t (Map k a))
listWithKeyShallowDiff initialVals valsChanged mkChild = do
let childValChangedSelector = fanMap $ fmap (Map.mapMaybe id) valsChanged
sentVals <- foldDyn applyMap (void initialVals) $ fmap (fmap void) valsChanged
let relevantPatch patch _ = case patch of
Nothing -> Just Nothing
Just _ -> Nothing
listHoldWithKey
initialVals
(attachWith (flip (Map.differenceWith relevantPatch))
(current sentVals)
valsChanged
)
$ \k v -> mkChild k v $ select childValChangedSelector $ Const2 k
listViewWithKey
:: (Ord k, Adjustable t m, PostBuild t m, MonadHold t m, MonadFix m)
=> Dynamic t (Map k v)
-> (k -> Dynamic t v -> m (Event t a))
-> m (Event t (Map k a))
listViewWithKey vals mkChild =
switch . fmap mergeMap <$> listViewWithKey' vals mkChild
listViewWithKey'
:: (Ord k, Adjustable t m, PostBuild t m, MonadHold t m, MonadFix m)
=> Dynamic t (Map k v)
-> (k -> Dynamic t v -> m a)
-> m (Behavior t (Map k a))
listViewWithKey' vals mkChild = current <$> listWithKey vals mkChild
selectViewListWithKey
:: forall t m k v a
. (Adjustable t m, Ord k, PostBuild t m, MonadHold t m, MonadFix m)
=> Dynamic t k
-> Dynamic t (Map k v)
-> (k -> Dynamic t v -> Dynamic t Bool -> m (Event t a))
-> m (Event t (k, a))
selectViewListWithKey selection vals mkChild = do
let selectionDemux = demux selection
selectChild <- listWithKey vals $ \k v -> do
let selected = demuxed selectionDemux k
selectSelf <- mkChild k v selected
return $ fmap ((,) k) selectSelf
return $ switchPromptlyDyn $ leftmost . Map.elems <$> selectChild
selectViewListWithKey_
:: forall t m k v a
. (Adjustable t m, Ord k, PostBuild t m, MonadHold t m, MonadFix m)
=> Dynamic t k
-> Dynamic t (Map k v)
-> (k -> Dynamic t v -> Dynamic t Bool -> m (Event t a))
-> m (Event t k)
selectViewListWithKey_ selection vals mkChild =
fmap fst <$> selectViewListWithKey selection vals mkChild
list
:: (Ord k, Adjustable t m, MonadHold t m, PostBuild t m, MonadFix m)
=> Dynamic t (Map k v)
-> (Dynamic t v -> m a)
-> m (Dynamic t (Map k a))
list dm mkChild = listWithKey dm (\_ dv -> mkChild dv)
simpleList
:: (Adjustable t m, MonadHold t m, PostBuild t m, MonadFix m)
=> Dynamic t [v]
-> (Dynamic t v -> m a)
-> m (Dynamic t [a])
simpleList xs mkChild =
fmap (fmap (map snd . Map.toList)) $ flip list mkChild $ fmap
(Map.fromList . zip [(1 :: Int) ..])
xs