@@ -3,11 +3,11 @@
33{-# LANGUAGE MultiParamTypeClasses #-}
44-- | This module provides a variation of 'Dynamic' values that uses cheap
55-- pointer equality checks to reduce the amount of signal propagation needed.
6−module Reflex.Dynamic.Nub
7− ( NubDynamic
8− , nubDynamic
9− , fromNubDynamic
10− , alreadyNubbedDynamic
6+module Reflex.Dynamic.Uniq
7+ ( UniqDynamic
8+ , uniqDynamic
9+ , fromUniqDynamic
10+ , alreadyUniqDynamic
1111 ) where
1212
1313import Control.Applicative (Applicative (..))
@@ -17,32 +17,33 @@ import Reflex.Dynamic
1717
1818-- | A 'Dynamic' whose 'updated' 'Event' will never fire with the same value as
1919-- the 'current' 'Behavior''s contents. In order to maintain this constraint,
20−-- the value inside a 'NubDynamic' is always evaluated to
20+-- the value inside a 'UniqDynamic' is always evaluated to
2121-- <https://wiki.haskell.org/Weak_head_normal_form weak head normal form>.
2222--
23−-- Internally, 'NubDynamic' uses pointer equality as a heuristic to avoid
23+-- Internally, 'UniqDynamic' uses pointer equality as a heuristic to avoid
2424-- unnecessary update propagation; this is much more efficient than performing
25−-- full comparisons. However, when the 'NubDynamic' is converted back into a
25+-- full comparisons. However, when the 'UniqDynamic' is converted back into a
2626-- regular 'Dynamic', a full comparison is performed.
27−newtype NubDynamic t a = NubDynamic { unNubDynamic :: Dynamic t a }
27+newtype UniqDynamic t a = UniqDynamic { unUniqDynamic :: Dynamic t a }
2828
29−-- | Construct a 'NubDynamic' by eliminating redundant updates from a 'Dynamic'.
30−nubDynamic :: Reflex t => Dynamic t a -> NubDynamic t a
31−nubDynamic d = NubDynamic $ unsafeBuildDynamic (sample $ current d) $ flip push (updated d) $ \new -> do --TODO: It would be very nice if we had an uncached push here
29+-- | Construct a 'UniqDynamic' by eliminating redundant updates from a 'Dynamic'.
30+uniqDynamic :: Reflex t => Dynamic t a -> UniqDynamic t a
31+uniqDynamic d = UniqDynamic $ unsafeBuildDynamic (sample $ current d) $ flip push (updated d) $ \new -> do --TODO: It would be very nice if we had an uncached push here
3232 old <- sample $ current d --TODO: Is it better to sample ourselves here?
3333 return $ unsafeJustChanged old new
3434
35−-- | Retrieve a normal 'Dynamic' from a 'NubDynamic'. This will perform a final
36−-- check using the output type's 'Eq' instance to ensure deterministic behavior.
35+-- | Retrieve a normal 'Dynamic' from a 'UniqDynamic'. This will perform a
36+-- final check using the output type's 'Eq' instance to ensure deterministic
37+-- behavior.
3738--
3839-- WARNING: If used with a type whose 'Eq' instance is not law-abiding -
39−-- specifically, if there are cases where @x /= x@, 'fromNubDynamic' may
40+-- specifically, if there are cases where @x /= x@, 'fromUniqDynamic' may
4041-- eliminate more 'updated' occurrences than it should. For example, NaN values
4142-- of 'Double' and 'Float' are considered unequal to themselves by the 'Eq'
42−-- instance, but can be equal by pointer equality. This may cause 'NubDynamic'
43+-- instance, but can be equal by pointer equality. This may cause 'UniqDynamic'
4344-- to lose changes from NaN to NaN.
44−fromNubDynamic :: (Reflex t, Eq a) => NubDynamic t a -> Dynamic t a
45−fromNubDynamic (NubDynamic d) = uniqDynBy superEq d
45+fromUniqDynamic :: (Reflex t, Eq a) => UniqDynamic t a -> Dynamic t a
46+fromUniqDynamic (UniqDynamic d) = uniqDynBy superEq d
4647 where
4748 -- Only consider values different if they fail both pointer equality /and/
4849 -- 'Eq' equality. This is to make things a bit more deterministic in the
@@ -53,12 +54,12 @@ fromNubDynamic (NubDynamic d) = uniqDynBy superEq d
5354 -- behavior deterministic in this case.
5455 superEq a b = a `unsafePtrEq` b || a == b
5556
56−-- | Create a NubDynamic without nubbing it on creation. This will be slightly
57−-- faster than nubDynamic when used with a Dynamic whose values are always (or
57+-- | Create a UniqDynamic without uniqing it on creation. This will be slightly
58+-- faster than uniqDynamic when used with a Dynamic whose values are always (or
5859-- nearly always) different from its previous values; if used with a Dynamic
59−-- whose values do not change frequently, it may be much slower than nubDynamic
60−alreadyNubbedDynamic :: Dynamic t a -> NubDynamic t a
61−alreadyNubbedDynamic = NubDynamic
60+-- whose values do not change frequently, it may be much slower than uniqDynamic
61+alreadyUniqDynamic :: Dynamic t a -> UniqDynamic t a
62+alreadyUniqDynamic = UniqDynamic
6263
6364unsafePtrEq :: a -> a -> Bool
6465unsafePtrEq a b = case a `seq` b `seq` reallyUnsafePtrEquality# a b of
@@ -71,30 +72,30 @@ unsafeJustChanged old new =
7172 then Nothing
7273 else Just new
7374
74−instance Reflex t => Accumulator t (NubDynamic t) where
75+instance Reflex t => Accumulator t (UniqDynamic t) where
7576 accumMaybeM f z e = do
7677 let f' old change = do
7778 mNew <- f old change
7879 return $ unsafeJustChanged old =<< mNew
7980 d <- accumMaybeM f' z e
80− return $ NubDynamic d
81+ return $ UniqDynamic d
8182 mapAccumMaybeM f z e = do
8283 let f' old change = do
8384 (mNew, output) <- f old change
8485 return (unsafeJustChanged old =<< mNew, output)
8586 (d, out) <- mapAccumMaybeM f' z e
86− return (NubDynamic d, out)
87+ return (UniqDynamic d, out)
8788
88−instance Reflex t => Functor (NubDynamic t) where
89− fmap f (NubDynamic d) = nubDynamic $ fmap f d
89+instance Reflex t => Functor (UniqDynamic t) where
90+ fmap f (UniqDynamic d) = uniqDynamic $ fmap f d
9091
91−instance Reflex t => Applicative (NubDynamic t) where
92− pure = NubDynamic . constDyn
93− NubDynamic a <*> NubDynamic b = nubDynamic $ a <*> b
92+instance Reflex t => Applicative (UniqDynamic t) where
93+ pure = UniqDynamic . constDyn
94+ UniqDynamic a <*> UniqDynamic b = uniqDynamic $ a <*> b
9495 _ *> b = b
9596 a <* _ = a
9697
97−instance Reflex t => Monad (NubDynamic t) where
98− NubDynamic x >>= f = nubDynamic $ x >>= unNubDynamic . f
98+instance Reflex t => Monad (UniqDynamic t) where
99+ UniqDynamic x >>= f = uniqDynamic $ x >>= unUniqDynamic . f
99100 _ >> b = b
100101 return = pure