on master help sign in
Remove Applicative instance of Fold
171907eAdithya Kumar
Changelog.md+2−5
@@ -1,10 +1,5 @@
1## Unreleased
1## Unreleased
2
2
3−### Notice
4−
5−* In the next major release the behaviour of `<*>` for folds will be updated
6− from `teeWith` to `splitWith` to reflect it's similarity with parsers.
7−
8### Behavioral changes
3### Behavioral changes
9
4
10* `Streamly.Prelude.fold` can now terminate early without consuming the entire
5* `Streamly.Prelude.fold` can now terminate early without consuming the entire
@@ -31,6 +26,8 @@
31 require an additional `MonadAsync` constraint. Several other
26 require an additional `MonadAsync` constraint. Several other
32 functions that used these functions also now require the additional
27 functions that used these functions also now require the additional
33 constraint.
28 constraint.
29+* Remove `Applicative` instance of folds. Please use `teeWith` or the `Tee` type
30+ as an alternative to Fold applicative.
34
31
35### Enhancements
32### Enhancements
36
33
benchmark/Streamly/Benchmark/Data/Fold.hs+10−7
@@ -70,7 +70,7 @@ takeLE value = IP.fold (FL.takeLE value FL.drain)
70
70
71{-# INLINE sequence_ #-}
71{-# INLINE sequence_ #-}
72sequence_ :: Monad m => Int -> Fold m a ()
72sequence_ :: Monad m => Int -> Fold m a ()
73−sequence_ value = foldr f (pure ()) (Prelude.replicate value (FL.takeLE 1 FL.drain))
73+sequence_ value = foldr f (FL.yield ()) (Prelude.replicate value (FL.takeLE 1 FL.drain))
74
74
75 where
75 where
76
76
@@ -118,10 +118,14 @@ split_ value =
118teeSumLength :: Monad m => SerialT m Int -> m (Int, Int)
118teeSumLength :: Monad m => SerialT m Int -> m (Int, Int)
119teeSumLength = IP.fold (FL.teeWith (,) FL.sum FL.length)
119teeSumLength = IP.fold (FL.teeWith (,) FL.sum FL.length)
120
120
121−{-# INLINE teeApplicative #-}
121+{-# INLINE teeAllAny #-}
122−teeApplicative :: (Monad m, Ord a) => a -> SerialT m a -> m (Bool, Bool)
122+teeAllAny :: (Monad m, Ord a) => a -> SerialT m a -> m (Bool, Bool)
123−teeApplicative value =
123+teeAllAny value = IP.fold (FL.teeWith (,) all_ any_)
124+
125+ where
126+
124− IP.fold ((,) <$> FL.all (<= value) <*> FL.any (> value))
127+ all_ = FL.all (<= value)
128+ any_ = FL.any (> value)
125
129
126{-# INLINE distribute #-}
130{-# INLINE distribute #-}
127distribute :: Monad m => SerialT m Int -> m [Int]
131distribute :: Monad m => SerialT m Int -> m [Int]
@@ -272,8 +276,7 @@ o_1_space_serial_composition value =
272 [ bgroup
276 [ bgroup
273 "composition"
277 "composition"
274 [ benchIOSink value "splitWith (all, any)" $ splitAllAny value
278 [ benchIOSink value "splitWith (all, any)" $ splitAllAny value
275− , benchIOSink value "teeApplicative (all, any)"
279+ , benchIOSink value "tee (all, any)" $ teeAllAny value
276− $ teeApplicative value
277 , benchIOSink value "many drain (takeLE 1)" many
280 , benchIOSink value "many drain (takeLE 1)" many
278 , benchIOSink value "tee (sum, length)" teeSumLength
281 , benchIOSink value "tee (sum, length)" teeSumLength
279 , benchIOSink value "distribute [sum, length]" distribute
282 , benchIOSink value "distribute [sum, length]" distribute
src/Streamly/Data/Fold.hs+1−1
@@ -199,7 +199,7 @@ module Streamly.Data.Fold
199 -- To compute the average of numbers in a stream without going through the
199 -- To compute the average of numbers in a stream without going through the
200 -- stream twice:
200 -- stream twice:
201 --
201 --
202− -- >>> let avg = (/) <$> Fold.sum <*> fmap fromIntegral Fold.length
202+ -- >>> let avg = Fold.teeWith (/) Fold.sum (fmap fromIntegral Fold.length)
203 -- >>> Stream.fold avg (Stream.enumerateFromTo 1.0 100.0)
203 -- >>> Stream.fold avg (Stream.enumerateFromTo 1.0 100.0)
204 -- 50.5
204 -- 50.5
205 --
205 --
src/Streamly/Internal/Data/Fold.hs+1−1
@@ -602,7 +602,7 @@ variance = mkAccum step begin done
602-- @since 0.7.0
602-- @since 0.7.0
603{-# INLINABLE stdDev #-}
603{-# INLINABLE stdDev #-}
604stdDev :: (Monad m, Floating a) => Fold m a a
604stdDev :: (Monad m, Floating a) => Fold m a a
605−stdDev = sqrt variance
605+stdDev = sqrt <$> variance
606
606
607-- | Compute an 'Int' sized polynomial rolling hash
607-- | Compute an 'Int' sized polynomial rolling hash
608--
608--
src/Streamly/Internal/Data/Fold/Types.hs−126
@@ -229,7 +229,6 @@ module Streamly.Internal.Data.Fold.Types
229 )
229 )
230where
230where
231
231
232−import Control.Applicative (liftA2)
233import Control.Concurrent (threadDelay, forkIO, killThread)
232import Control.Concurrent (threadDelay, forkIO, killThread)
234import Control.Concurrent.MVar (MVar, newMVar, swapMVar, readMVar)
233import Control.Concurrent.MVar (MVar, newMVar, swapMVar, readMVar)
235import Control.Exception (SomeException(..), catch, mask)
234import Control.Exception (SomeException(..), catch, mask)
@@ -573,26 +572,6 @@ data GenericRunner sL sR bL bR
573 | RunLeft !sL !bR
572 | RunLeft !sL !bR
574 | RunRight !bL !sR
573 | RunRight !bL !sR
575
574
576−-- | The fold resulting from '<*>' distributes its input to both the argument
577−-- folds and combines their output using the supplied function.
578−--
579−-- __Note:__ The Applicative behaviour will change in the next major release.
580−--
581−instance Monad m => Applicative (Fold m a) where
582− {-# INLINE pure #-}
583− pure = yield
584−
585− -- | __Notice:__ In the next major release the behaviour of @<*>@ for folds
586− -- will be updated from 'teeWith' to 'splitWith' to reflect it's similarity
587− -- with parsers.
588− {-# INLINE (<*>) #-}
589− (<*>) = teeWith ($)
590−
591−#if MIN_VERSION_base(4,10,0)
592− {-# INLINE liftA2 #-}
593− liftA2 f x = (<*>) (fmap f x)
594−#endif
595−
596-- | @teeWith k f1 f2@ distributes its input to both @f1@ and @f2@ until both
575-- | @teeWith k f1 f2@ distributes its input to both @f1@ and @f2@ until both
597-- of them terminate and combines their output using @k@.
576-- of them terminate and combines their output using @k@.
598--
577--
@@ -746,111 +725,6 @@ concatMap f (Fold stepa initiala extracta) = Fold stepc initialc extractc
746 Partial s -> e s
725 Partial s -> e s
747 Done c -> return c
726 Done c -> return c
748
727
749−-- | Combines the outputs of the folds (the type @b@) using their 'Semigroup'
750−-- instances.
751−instance (Semigroup b, Monad m) => Semigroup (Fold m a b) where
752− {-# INLINE (<>) #-}
753− (<>) = liftA2 (<>)
754−
755−-- | Combines the outputs of the folds (the type @b@) using their 'Monoid'
756−-- instances.
757−instance (Semigroup b, Monoid b, Monad m) => Monoid (Fold m a b) where
758− {-# INLINE mempty #-}
759− mempty = pure mempty
760−
761− {-# INLINE mappend #-}
762− mappend = (<>)
763−
764−-- | Combines the fold outputs (type @b@) using their 'Num' instances.
765−instance (Monad m, Num b) => Num (Fold m a b) where
766− {-# INLINE fromInteger #-}
767− fromInteger = pure . fromInteger
768−
769− {-# INLINE negate #-}
770− negate = fmap negate
771−
772− {-# INLINE abs #-}
773− abs = fmap abs
774−
775− {-# INLINE signum #-}
776− signum = fmap signum
777−
778− {-# INLINE (+) #-}
779− (+) = liftA2 (+)
780−
781− {-# INLINE (*) #-}
782− (*) = liftA2 (*)
783−
784− {-# INLINE (-) #-}
785− (-) = liftA2 (-)
786−
787−-- | Combines the fold outputs (type @b@) using their 'Fractional' instances.
788−instance (Monad m, Fractional b) => Fractional (Fold m a b) where
789− {-# INLINE fromRational #-}
790− fromRational = pure . fromRational
791−
792− {-# INLINE recip #-}
793− recip = fmap recip
794−
795− {-# INLINE (/) #-}
796− (/) = liftA2 (/)
797−
798−-- | Combines the fold outputs using their 'Floating' instances.
799−instance (Monad m, Floating b) => Floating (Fold m a b) where
800− {-# INLINE pi #-}
801− pi = pure pi
802−
803− {-# INLINE exp #-}
804− exp = fmap exp
805−
806− {-# INLINE sqrt #-}
807− sqrt = fmap sqrt
808−
809− {-# INLINE log #-}
810− log = fmap log
811−
812− {-# INLINE sin #-}
813− sin = fmap sin
814−
815− {-# INLINE tan #-}
816− tan = fmap tan
817−
818− {-# INLINE cos #-}
819− cos = fmap cos
820−
821− {-# INLINE asin #-}
822− asin = fmap asin
823−
824− {-# INLINE atan #-}
825− atan = fmap atan
826−
827− {-# INLINE acos #-}
828− acos = fmap acos
829−
830− {-# INLINE sinh #-}
831− sinh = fmap sinh
832−
833− {-# INLINE tanh #-}
834− tanh = fmap tanh
835−
836− {-# INLINE cosh #-}
837− cosh = fmap cosh
838−
839− {-# INLINE asinh #-}
840− asinh = fmap asinh
841−
842− {-# INLINE atanh #-}
843− atanh = fmap atanh
844−
845− {-# INLINE acosh #-}
846− acosh = fmap acosh
847−
848− {-# INLINE (**) #-}
849− (**) = liftA2 (**)
850−
851− {-# INLINE logBase #-}
852− logBase = liftA2 logBase
853−
854------------------------------------------------------------------------------
728------------------------------------------------------------------------------
855-- Internal APIs
729-- Internal APIs
856------------------------------------------------------------------------------
730------------------------------------------------------------------------------
src/Streamly/Prelude.hs+2−2
@@ -997,12 +997,12 @@ import Streamly.Internal.Data.Stream.IsStream
997-- running average of elements is no more than 10:
997-- running average of elements is no more than 10:
998--
998--
999-- >>> import Data.Maybe (fromJust)
999-- >>> import Data.Maybe (fromJust)
1000−-- >>> let avg = (/) <$> Fold.sum <*> fmap fromIntegral Fold.length
1000+-- >>> let avg = Fold.teeWith (/) Fold.sum (fmap fromIntegral Fold.length)
1001-- >>> :{
1001-- >>> :{
1002-- Stream.toList
1002-- Stream.toList
1003-- $ Stream.map (fromJust . fst)
1003-- $ Stream.map (fromJust . fst)
1004-- $ Stream.takeWhile (\(_,x) -> x <= 10)
1004-- $ Stream.takeWhile (\(_,x) -> x <= 10)
1005−-- $ Stream.postscan ((,) <$> Fold.last <*> avg) (Stream.enumerateFromTo 1.0 100.0)
1005+-- $ Stream.postscan (Fold.tee Fold.last avg) (Stream.enumerateFromTo 1.0 100.0)
1006-- :}
1006-- :}
1007-- [1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0]
1007-- [1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0]
1008--
1008--