Rename Scanl smart constructors

This commit is contained in:
Harendra Kumar 2024-08-07 10:01:32 +05:30
parent 0be294a01d
commit c321238222
10 changed files with 96 additions and 95 deletions

View File

@ -406,7 +406,7 @@ foldl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> m b
foldl' f z = Stream.fold (Fold.foldl' f z)
scanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
scanl' f z = Stream.scanl (Scanl.scanl' f z)
scanl' f z = Stream.scanl (Scanl.mkScanl f z)
#endif
{-# INLINE transformMapM #-}

View File

@ -201,7 +201,7 @@ o_1_space_mappingX4 value =
sieveScan :: Monad m => Stream m Int -> Stream m Int
sieveScan =
Stream.mapMaybe snd
. Stream.scanl (Scanl.scanlM' (\(primes, _) n -> do
. Stream.scanl (Scanl.mkScanlM (\(primes, _) n -> do
return $
let ps = takeWhile (\p -> p * p <= n) primes
in if all (\p -> n `mod` p /= 0) ps

View File

@ -22,6 +22,7 @@
>>> import Streamly.Data.Stream (Stream)
>>> import qualified Streamly.Data.Array as Array
>>> import qualified Streamly.Data.Fold as Fold
>>> import qualified Streamly.Data.Scanl as Scanl
>>> import qualified Streamly.Data.Stream as Stream
>>> import qualified Streamly.Data.StreamK as StreamK
>>> import qualified Streamly.Data.Unfold as Unfold

View File

@ -21,11 +21,11 @@ module Streamly.Data.Scanl
Scanl -- (..)
-- * Constructors
, scanl'
, scanlM'
, scanl1'
, scanl1M'
, scanr'
, mkScanl
, mkScanlM
, mkScanl1
, mkScanl1M
, mkScanr
-- * Scans
-- ** Accumulators

View File

@ -347,12 +347,12 @@ module Streamly.Data.Stream
-- ** Scanning By 'Scanl'
-- | Useful idioms:
--
-- >>> scanl' f z = Stream.scanl (Scanl.scanl' f z)
-- >>> scanlM' f z = Stream.scanl (Scanl.scanlM' f z)
-- >>> postscanl' f z = Stream.postscanl (Scanl.scanl' f z)
-- >>> postscanlM' f z = Stream.postscanl (Scanl.scanlM' f z)
-- >>> scanl1' f = Stream.catMaybes . Stream.scanl (Scanl.scanl1' f)
-- >>> scanl1M' f = Stream.catMaybes . Stream.scanl (Scanl.scanl1M' f)
-- >>> scanl' f z = Stream.scanl (Scanl.mkScanl f z)
-- >>> scanlM' f z = Stream.scanl (Scanl.mkScanlM f z)
-- >>> postscanl' f z = Stream.postscanl (Scanl.mkScanl f z)
-- >>> postscanlM' f z = Stream.postscanl (Scanl.mkScanlM f z)
-- >>> scanl1' f = Stream.catMaybes . Stream.scanl (Scanl.mkScanl1 f)
-- >>> scanl1M' f = Stream.catMaybes . Stream.scanl (Scanl.mkScanl1M f)
, scanl
, postscanl
-- XXX postscan1 can be implemented using Monoids or Refolds.

View File

@ -591,7 +591,7 @@ scanlMany = scanWith True
--
{-# INLINE_NORMAL deleteBy #-}
deleteBy :: Monad m => (a -> a -> Bool) -> a -> Scanl m a (Maybe a)
deleteBy eq x0 = fmap extract $ scanl' step (Tuple' False Nothing)
deleteBy eq x0 = fmap extract $ mkScanl step (Tuple' False Nothing)
where
@ -746,12 +746,12 @@ drainMapM f = lmapM f drain
-- | Returns the latest element of the input stream, if any.
--
-- >>> latest = Fold.scanl1' (\_ x -> x)
-- >>> latest = Scanl.mkScanl1 (\_ x -> x)
-- >>> latest = fmap getLast $ Fold.foldMap (Last . Just)
--
{-# INLINE latest #-}
latest :: Monad m => Scanl m a (Maybe a)
latest = scanl1' (\_ x -> x)
latest = mkScanl1 (\_ x -> x)
-- | Terminates with 'Nothing' as soon as it finds an element different than
-- the previous one, returns 'the' element if the entire input consists of the
@ -759,7 +759,7 @@ latest = scanl1' (\_ x -> x)
--
{-# INLINE the #-}
the :: (Monad m, Eq a) => Scanl m a (Maybe a)
the = scant' step initial id
the = mkScant step initial id
where
@ -783,7 +783,7 @@ the = scant' step initial id
--
-- Same as following but numerically stable:
--
-- >>> sum = Fold.scanl' (+) 0
-- >>> sum = Scanl.mkScanl (+) 0
-- >>> sum = fmap Data.Monoid.getSum $ Fold.foldMap Data.Monoid.Sum
--
{-# INLINE sum #-}
@ -800,7 +800,7 @@ sum = Scanl.cumulative Scanl.windowSum
--
{-# INLINE product #-}
product :: (Monad m, Num a, Eq a) => Scanl m a a
product = scant' step (Partial 1) id
product = mkScant step (Partial 1) id
where
@ -818,7 +818,7 @@ product = scant' step (Partial 1) id
--
{-# INLINE maximumBy #-}
maximumBy :: Monad m => (a -> a -> Ordering) -> Scanl m a (Maybe a)
maximumBy cmp = scanl1' max'
maximumBy cmp = mkScanl1 max'
where
@ -831,8 +831,8 @@ maximumBy cmp = scanl1' max'
--
-- Definitions:
--
-- >>> maximum = Fold.maximumBy compare
-- >>> maximum = Fold.scanl1' max
-- >>> maximum = Scanl.maximumBy compare
-- >>> maximum = Scanl.mkScanl1 max
--
-- Same as the following but without a default maximum. The 'Max' Monoid uses
-- the 'minBound' as the default maximum:
@ -841,13 +841,13 @@ maximumBy cmp = scanl1' max'
--
{-# INLINE maximum #-}
maximum :: (Monad m, Ord a) => Scanl m a (Maybe a)
maximum = scanl1' max
maximum = mkScanl1 max
-- | Computes the minimum element with respect to the given comparison function
--
{-# INLINE minimumBy #-}
minimumBy :: Monad m => (a -> a -> Ordering) -> Scanl m a (Maybe a)
minimumBy cmp = scanl1' min'
minimumBy cmp = mkScanl1 min'
where
@ -861,8 +861,8 @@ minimumBy cmp = scanl1' min'
--
-- Definitions:
--
-- >>> minimum = Fold.minimumBy compare
-- >>> minimum = Fold.scanl1' min
-- >>> minimum = Scanl.minimumBy compare
-- >>> minimum = Scanl.mkScanl1 min
--
-- Same as the following but without a default minimum. The 'Min' Monoid uses the
-- 'maxBound' as the default maximum:
@ -871,7 +871,7 @@ minimumBy cmp = scanl1' min'
--
{-# INLINE minimum #-}
minimum :: (Monad m, Ord a) => Scanl m a (Maybe a)
minimum = scanl1' min
minimum = mkScanl1 min
------------------------------------------------------------------------------
-- To Summary (Statistical)
@ -882,7 +882,7 @@ minimum = scanl1' min
--
{-# INLINE mean #-}
mean :: (Monad m, Fractional a) => Scanl m a a
mean = fmap done $ scanl' step begin
mean = fmap done $ mkScanl step begin
where
@ -907,7 +907,7 @@ mean = fmap done $ scanl' step begin
--
{-# INLINE rollingHashWithSalt #-}
rollingHashWithSalt :: (Monad m, Enum a) => Int64 -> Scanl m a Int64
rollingHashWithSalt = scanl' step
rollingHashWithSalt = mkScanl step
where
@ -947,7 +947,7 @@ rollingHashFirstN n = take n rollingHash
--
-- Definition:
--
-- >>> sconcat = Fold.scanl' (<>)
-- >>> sconcat = Scanl.mkScanl (<>)
--
-- >>> semigroups = fmap Data.Monoid.Sum $ Stream.enumerateFromTo 1 10
-- >>> Stream.fold (Fold.sconcat 10) semigroups
@ -955,7 +955,7 @@ rollingHashFirstN n = take n rollingHash
--
{-# INLINE sconcat #-}
sconcat :: (Monad m, Semigroup a) => a -> Scanl m a a
sconcat = scanl' (<>)
sconcat = mkScanl (<>)
-- | Monoid concat. Fold an input stream consisting of monoidal elements using
-- 'mappend' and 'mempty'.
@ -1004,7 +1004,7 @@ foldMap f = lmap f mconcat
--
{-# INLINE foldMapM #-}
foldMapM :: (Monad m, Monoid b) => (a -> m b) -> Scanl m a b
foldMapM act = scanlM' step (pure mempty)
foldMapM act = mkScanlM step (pure mempty)
where
@ -1024,7 +1024,7 @@ foldMapM act = scanlM' step (pure mempty)
--
-- Definition:
--
-- >>> toListRev = Fold.scanl' (flip (:)) []
-- >>> toListRev = Fold.mkScanl (flip (:)) []
--
-- /Warning!/ working on large lists accumulated as buffers in memory could be
-- very inefficient, consider using "Streamly.Array" instead.
@ -1033,7 +1033,7 @@ foldMapM act = scanlM' step (pure mempty)
-- xn : ... : x2 : x1 : []
{-# INLINE toListRev #-}
toListRev :: Monad m => Scanl m a [a]
toListRev = scanl' (flip (:)) []
toListRev = mkScanl (flip (:)) []
------------------------------------------------------------------------------
-- Partial Folds
@ -1061,7 +1061,7 @@ drainN n = take n drain
-- /Pre-release/
{-# INLINE genericIndex #-}
genericIndex :: (Integral i, Monad m) => i -> Scanl m a (Maybe a)
genericIndex i = scant' step (Partial 0) (const Nothing)
genericIndex i = mkScant step (Partial 0) (const Nothing)
where
@ -1087,7 +1087,7 @@ index = genericIndex
--
{-# INLINE maybe #-}
maybe :: Monad m => (a -> Maybe b) -> Scanl m a (Maybe b)
maybe f = scant' (const (Done . f)) (Partial Nothing) id
maybe f = mkScant (const (Done . f)) (Partial Nothing) id
-- | Consume a single element and return it if it passes the predicate else
-- return 'Nothing'.
@ -1179,7 +1179,7 @@ find p = findM (return . p)
--
{-# INLINE lookup #-}
lookup :: (Eq a, Monad m) => a -> Scanl m (a,b) (Maybe b)
lookup a0 = scant' step (Partial ()) (const Nothing)
lookup a0 = mkScant step (Partial ()) (const Nothing)
where
@ -1192,7 +1192,7 @@ lookup a0 = scant' step (Partial ()) (const Nothing)
--
{-# INLINE findIndex #-}
findIndex :: Monad m => (a -> Bool) -> Scanl m a (Maybe Int)
findIndex predicate = scant' step (Partial 0) (const Nothing)
findIndex predicate = mkScant step (Partial 0) (const Nothing)
where
@ -1209,7 +1209,7 @@ findIndex predicate = scant' step (Partial 0) (const Nothing)
findIndices :: Monad m => (a -> Bool) -> Scanl m a (Maybe Int)
findIndices predicate =
-- XXX implement by combining indexing and filtering scans
fmap (either (Prelude.const Nothing) Just) $ scanl' step (Left (-1))
fmap (either (Prelude.const Nothing) Just) $ mkScanl step (Left (-1))
where
@ -1259,7 +1259,7 @@ elemIndex a = findIndex (== a)
--
{-# INLINE null #-}
null :: Monad m => Scanl m a Bool
null = scant' (\() _ -> Done False) (Partial ()) (const True)
null = mkScant (\() _ -> Done False) (Partial ()) (const True)
-- | Returns 'True' if any element of the input satisfies the predicate.
--
@ -1274,7 +1274,7 @@ null = scant' (\() _ -> Done False) (Partial ()) (const True)
--
{-# INLINE any #-}
any :: Monad m => (a -> Bool) -> Scanl m a Bool
any predicate = scant' step initial id
any predicate = mkScant step initial id
where
@ -1308,7 +1308,7 @@ elem a = any (== a)
--
{-# INLINE all #-}
all :: Monad m => (a -> Bool) -> Scanl m a Bool
all predicate = scant' step initial id
all predicate = mkScant step initial id
where
@ -2159,7 +2159,7 @@ zipStream = zipStreamWithM (curry return)
--
{-# INLINE indexingWith #-}
indexingWith :: Monad m => Int -> (Int -> Int) -> Scanl m a (Maybe (Int, a))
indexingWith i f = fmap toMaybe $ scanl' step initial
indexingWith i f = fmap toMaybe $ mkScanl step initial
where

View File

@ -121,22 +121,22 @@ import Streamly.Internal.Data.Scanl.Type
--
-- Definition:
--
-- >>> toSet = Scanl.scanl' (flip Set.insert) Set.empty
-- >>> toSet = Scanl.mkScanl (flip Set.insert) Set.empty
--
{-# INLINE toSet #-}
toSet :: (Monad m, Ord a) => Scanl m a (Set a)
toSet = scanl' (flip Set.insert) Set.empty
toSet = mkScanl (flip Set.insert) Set.empty
-- | Scan the input adding it to an int set. For integer inputs this performs
-- better than 'toSet'.
--
-- Definition:
--
-- >>> toIntSet = Scanl.scanl' (flip IntSet.insert) IntSet.empty
-- >>> toIntSet = Scanl.mkScanl (flip IntSet.insert) IntSet.empty
--
{-# INLINE toIntSet #-}
toIntSet :: Monad m => Scanl m Int IntSet
toIntSet = scanl' (flip IntSet.insert) IntSet.empty
toIntSet = mkScanl (flip IntSet.insert) IntSet.empty
-- XXX Name as nubOrd? Or write a nubGeneric
@ -152,7 +152,7 @@ toIntSet = scanl' (flip IntSet.insert) IntSet.empty
-- /Pre-release/
{-# INLINE nub #-}
nub :: (Monad m, Ord a) => Scanl m a (Maybe a)
nub = fmap (\(Tuple' _ x) -> x) $ scanl' step initial
nub = fmap (\(Tuple' _ x) -> x) $ mkScanl step initial
where
@ -168,7 +168,7 @@ nub = fmap (\(Tuple' _ x) -> x) $ scanl' step initial
-- /Pre-release/
{-# INLINE nubInt #-}
nubInt :: Monad m => Scanl m Int (Maybe Int)
nubInt = fmap (\(Tuple' _ x) -> x) $ scanl' step initial
nubInt = fmap (\(Tuple' _ x) -> x) $ mkScanl step initial
where
@ -487,7 +487,7 @@ demuxIO getKey = fmap snd . demuxUsingMapIO getKey
{-# INLINE kvToMapOverwriteGeneric #-}
kvToMapOverwriteGeneric :: (Monad m, IsMap f) => Scanl m (Key f, a) (f a)
kvToMapOverwriteGeneric =
scanl' (\kv (k, v) -> IsMap.mapInsert k v kv) IsMap.mapEmpty
mkScanl (\kv (k, v) -> IsMap.mapInsert k v kv) IsMap.mapEmpty
{-# INLINE demuxToContainer #-}
demuxToContainer :: (Monad m, IsMap f, Traversable f) =>

View File

@ -78,14 +78,14 @@ module Streamly.Internal.Data.Scanl.Type
, Scanl (..)
-- * Constructors
, scanl'
, scanlM'
, scanl1'
, scanl1M'
, scant'
, scantM'
, scanr'
, scanrM'
, mkScanl
, mkScanlM
, mkScanl1
, mkScanl1M
, mkScant
, mkScantM
, mkScanr
, mkScanrM
-- * Scans
, const
@ -323,9 +323,9 @@ rmapM f (Scanl step initial extract final) =
-- mkfoldlx step initial extract = fmap extract (foldl' step initial)
-- @
--
{-# INLINE scanl' #-}
scanl' :: Monad m => (b -> a -> b) -> b -> Scanl m a b
scanl' step initial =
{-# INLINE mkScanl #-}
mkScanl :: Monad m => (b -> a -> b) -> b -> Scanl m a b
mkScanl step initial =
Scanl
(\s a -> return $ Partial $ step s a)
(return (Partial initial))
@ -342,9 +342,9 @@ scanl' step initial =
-- mkFoldlxM step initial extract = rmapM extract (foldlM' step initial)
-- @
--
{-# INLINE scanlM' #-}
scanlM' :: Monad m => (b -> a -> m b) -> m b -> Scanl m a b
scanlM' step initial =
{-# INLINE mkScanlM #-}
mkScanlM :: Monad m => (b -> a -> m b) -> m b -> Scanl m a b
mkScanlM step initial =
Scanl (\s a -> Partial <$> step s a) (Partial <$> initial) return return
-- | Maps a function on the output of the fold (the type @b@).
@ -363,9 +363,9 @@ instance Functor m => Functor (Scanl m a) where
-- starting value. Returns Nothing if the stream is empty.
--
-- /Pre-release/
{-# INLINE scanl1' #-}
scanl1' :: Monad m => (a -> a -> a) -> Scanl m a (Maybe a)
scanl1' step = fmap toMaybe $ scanl' step1 Nothing'
{-# INLINE mkScanl1 #-}
mkScanl1 :: Monad m => (a -> a -> a) -> Scanl m a (Maybe a)
mkScanl1 step = fmap toMaybe $ mkScanl step1 Nothing'
where
@ -375,9 +375,9 @@ scanl1' step = fmap toMaybe $ scanl' step1 Nothing'
-- | Like 'foldl1\'' but with a monadic step function.
--
-- /Pre-release/
{-# INLINE scanl1M' #-}
scanl1M' :: Monad m => (a -> a -> m a) -> Scanl m a (Maybe a)
scanl1M' step = fmap toMaybe $ scanlM' step1 (return Nothing')
{-# INLINE mkScanl1M #-}
mkScanl1M :: Monad m => (a -> a -> m a) -> Scanl m a (Maybe a)
mkScanl1M step = fmap toMaybe $ mkScanlM step1 (return Nothing')
where
@ -445,9 +445,9 @@ fromScan (Scan consume initial) =
-- >>> Stream.fold (Fold.foldr' (:) []) $ Stream.enumerateFromTo 1 5
-- [1,2,3,4,5]
--
{-# INLINE scanr' #-}
scanr' :: Monad m => (a -> b -> b) -> b -> Scanl m a b
scanr' f z = fmap ($ z) $ scanl' (\g x -> g . f x) id
{-# INLINE mkScanr #-}
mkScanr :: Monad m => (a -> b -> b) -> b -> Scanl m a b
mkScanr f z = fmap ($ z) $ mkScanl (\g x -> g . f x) id
-- XXX we have not seen any use of this yet, not releasing until we have a use
-- case.
@ -461,10 +461,10 @@ scanr' f z = fmap ($ z) $ scanl' (\g x -> g . f x) id
-- See also: 'Streamly.Internal.Data.Stream.foldrM'
--
-- /Pre-release/
{-# INLINE scanrM' #-}
scanrM' :: Monad m => (a -> b -> m b) -> m b -> Scanl m a b
scanrM' g z =
rmapM (z >>=) $ scanlM' (\f x -> return $ g x >=> f) (return return)
{-# INLINE mkScanrM #-}
mkScanrM :: Monad m => (a -> b -> m b) -> m b -> Scanl m a b
mkScanrM g z =
rmapM (z >>=) $ mkScanlM (\f x -> return $ g x >=> f) (return return)
------------------------------------------------------------------------------
-- General fold constructors
@ -489,9 +489,9 @@ scanrM' g z =
--
-- /Pre-release/
--
{-# INLINE scant' #-}
scant' :: Monad m => (s -> a -> Step s b) -> Step s b -> (s -> b) -> Scanl m a b
scant' step initial extract =
{-# INLINE mkScant #-}
mkScant :: Monad m => (s -> a -> Step s b) -> Step s b -> (s -> b) -> Scanl m a b
mkScant step initial extract =
Scanl
(\s a -> return $ step s a)
(return initial)
@ -507,9 +507,9 @@ scant' step initial extract =
--
-- /Pre-release/
--
{-# INLINE scantM' #-}
scantM' :: (s -> a -> m (Step s b)) -> m (Step s b) -> (s -> m b) -> Scanl m a b
scantM' step initial extract = Scanl step initial extract extract
{-# INLINE mkScantM #-}
mkScantM :: (s -> a -> m (Step s b)) -> m (Step s b) -> (s -> m b) -> Scanl m a b
mkScantM step initial extract = Scanl step initial extract extract
------------------------------------------------------------------------------
-- Refold
@ -537,7 +537,7 @@ fromRefold (Refold step inject extract) c =
--
{-# INLINE drain #-}
drain :: Monad m => Scanl m a ()
drain = scanl' (\_ _ -> ()) ()
drain = mkScanl (\_ _ -> ()) ()
-- | Folds the input stream to a list.
--
@ -549,7 +549,7 @@ drain = scanl' (\_ _ -> ()) ()
--
{-# INLINE toList #-}
toList :: Monad m => Scanl m a [a]
toList = scanr' (:) []
toList = mkScanr (:) []
-- | Buffers the input stream to a pure stream in the reverse order of the
-- input.
@ -564,7 +564,7 @@ toList = scanr' (:) []
-- xn : ... : x2 : x1 : []
{-# INLINE toStreamKRev #-}
toStreamKRev :: Monad m => Scanl m a (K.StreamK n a)
toStreamKRev = scanl' (flip K.cons) K.nil
toStreamKRev = mkScanl (flip K.cons) K.nil
-- | A fold that buffers its input to a pure stream.
--
@ -574,7 +574,7 @@ toStreamKRev = scanl' (flip K.cons) K.nil
-- /Internal/
{-# INLINE toStreamK #-}
toStreamK :: Monad m => Scanl m a (K.StreamK n a)
toStreamK = scanr' K.cons K.nil
toStreamK = mkScanr K.cons K.nil
-- | Like 'length', except with a more general 'Num' return value
--
@ -586,7 +586,7 @@ toStreamK = scanr' K.cons K.nil
-- /Pre-release/
{-# INLINE genericLength #-}
genericLength :: (Monad m, Num b) => Scanl m a b
genericLength = scanl' (\n _ -> n + 1) 0
genericLength = mkScanl (\n _ -> n + 1) 0
-- | Determine the length of the input stream.
--
@ -1234,7 +1234,7 @@ postscanlMaybe f1 f2 = postscanl f1 (catMaybes f2)
--
{-# INLINE filtering #-}
filtering :: Monad m => (a -> Bool) -> Scanl m a (Maybe a)
filtering f = scanl' step Nothing
filtering f = mkScanl step Nothing
where
@ -1312,7 +1312,7 @@ data Tuple'Fused a b = Tuple'Fused !a !b deriving Show
{-# INLINE taking #-}
taking :: Monad m => Int -> Scanl m a (Maybe a)
taking n = scant' step initial extract
taking n = mkScant step initial extract
where
@ -1330,7 +1330,7 @@ taking n = scant' step initial extract
{-# INLINE dropping #-}
dropping :: Monad m => Int -> Scanl m a (Maybe a)
dropping n = scant' step initial extract
dropping n = mkScant step initial extract
where

View File

@ -186,7 +186,7 @@ cumulative = Scanl.lmap (, Nothing)
{-# INLINE windowRollingMapM #-}
windowRollingMapM :: Monad m =>
(Maybe a -> a -> m (Maybe b)) -> Scanl m (a, Maybe a) (Maybe b)
windowRollingMapM f = Scanl.scanlM' f1 initial
windowRollingMapM f = Scanl.mkScanlM f1 initial
where
@ -201,7 +201,7 @@ windowRollingMapM f = Scanl.scanlM' f1 initial
{-# INLINE windowRollingMap #-}
windowRollingMap :: Monad m =>
(Maybe a -> a -> Maybe b) -> Scanl m (a, Maybe a) (Maybe b)
windowRollingMap f = Scanl.scanl' f1 initial
windowRollingMap f = Scanl.mkScanl f1 initial
where
@ -299,7 +299,7 @@ windowSum = Scanl step initial extract extract
--
{-# INLINE windowLength #-}
windowLength :: (Monad m, Num b) => Scanl m (a, Maybe a) b
windowLength = Scanl.scanl' step 0
windowLength = Scanl.mkScanl step 0
where

View File

@ -835,7 +835,7 @@ sampleBurst sampleAtEnd gap xs =
-- but the tick stream should work well as long as the timer
-- granularity is small enough compared to the gap.
Stream.mapMaybe extract
$ Stream.scanl (Scanl.scanl' step BurstNone)
$ Stream.scanl (Scanl.mkScanl step BurstNone)
$ Stream.timeIndexed
$ interject (return Nothing) 0.01 (fmap Just xs)