on master help sign in
Use the SPEC argument on all recursive cases
00f5d9fHarendra Kumar
core/src/Streamly/Internal/Data/Stream/StreamD/Eliminate.hs+64−56
@@ -228,6 +228,7 @@ parseBreak (PRD.Parser pstep initial extract) stream@(Stream step state) = do
228-- Specialized Folds
228-- Specialized Folds
229------------------------------------------------------------------------------
229------------------------------------------------------------------------------
230
230
231+-- benchmark after dropping 1 item from stream or using unfolds
231{-# INLINE_NORMAL null #-}
232{-# INLINE_NORMAL null #-}
232null :: Monad m => Stream m a -> m Bool
233null :: Monad m => Stream m a -> m Bool
233null = foldrM (\_ _ -> return False) (return True)
234null = foldrM (\_ _ -> return False) (return True)
@@ -243,13 +244,13 @@ headElse a = foldrM (\x _ -> return x) (return a)
243-- Does not fuse, has the same performance as the StreamK version.
244-- Does not fuse, has the same performance as the StreamK version.
244{-# INLINE_NORMAL tail #-}
245{-# INLINE_NORMAL tail #-}
245tail :: Monad m => Stream m a -> m (Maybe (Stream m a))
246tail :: Monad m => Stream m a -> m (Maybe (Stream m a))
246−tail (UnStream step state) = go state
247+tail (UnStream step state) = go SPEC state
247 where
248 where
248− go st = do
249+ go !_ st = do
249 r <- step defState st
250 r <- step defState st
250 case r of
251 case r of
251 Yield _ s -> return (Just $ Stream step s)
252 Yield _ s -> return (Just $ Stream step s)
252− Skip s -> go s
253+ Skip s -> go SPEC s
253 Stop -> return Nothing
254 Stop -> return Nothing
254
255
255-- XXX will it fuse? need custom impl?
256-- XXX will it fuse? need custom impl?
@@ -257,18 +258,19 @@ tail (UnStream step state) = go state
257last :: Monad m => Stream m a -> m (Maybe a)
258last :: Monad m => Stream m a -> m (Maybe a)
258last = foldl' (\_ y -> Just y) Nothing
259last = foldl' (\_ y -> Just y) Nothing
259
260
261+-- XXX Use the foldrM based impl instead
260{-# INLINE_NORMAL elem #-}
262{-# INLINE_NORMAL elem #-}
261elem :: (Monad m, Eq a) => a -> Stream m a -> m Bool
263elem :: (Monad m, Eq a) => a -> Stream m a -> m Bool
262-- elem e m = foldrM (\x xs -> if x == e then return True else xs) (return False) m
264-- elem e m = foldrM (\x xs -> if x == e then return True else xs) (return False) m
263−elem e (Stream step state) = go state
265+elem e (Stream step state) = go SPEC state
264 where
266 where
265− go st = do
267+ go !_ st = do
266 r <- step defState st
268 r <- step defState st
267 case r of
269 case r of
268 Yield x s
270 Yield x s
269− | x == e -> return True
271+ | x == e -> return True
270− | otherwise -> go s
272+ | otherwise -> go SPEC s
271− Skip s -> go s
273+ Skip s -> go SPEC s
272 Stop -> return False
274 Stop -> return False
273
275
274{-# INLINE_NORMAL notElem #-}
276{-# INLINE_NORMAL notElem #-}
@@ -278,118 +280,124 @@ notElem e s = fmap not (elem e s)
278{-# INLINE_NORMAL all #-}
280{-# INLINE_NORMAL all #-}
279all :: Monad m => (a -> Bool) -> Stream m a -> m Bool
281all :: Monad m => (a -> Bool) -> Stream m a -> m Bool
280-- all p m = foldrM (\x xs -> if p x then xs else return False) (return True) m
282-- all p m = foldrM (\x xs -> if p x then xs else return False) (return True) m
281−all p (Stream step state) = go state
283+all p (Stream step state) = go SPEC state
282 where
284 where
283− go st = do
285+ go !_ st = do
284 r <- step defState st
286 r <- step defState st
285 case r of
287 case r of
286 Yield x s
288 Yield x s
287− | p x -> go s
289+ | p x -> go SPEC s
288 | otherwise -> return False
290 | otherwise -> return False
289− Skip s -> go s
291+ Skip s -> go SPEC s
290 Stop -> return True
292 Stop -> return True
291
293
292{-# INLINE_NORMAL any #-}
294{-# INLINE_NORMAL any #-}
293any :: Monad m => (a -> Bool) -> Stream m a -> m Bool
295any :: Monad m => (a -> Bool) -> Stream m a -> m Bool
294-- any p m = foldrM (\x xs -> if p x then return True else xs) (return False) m
296-- any p m = foldrM (\x xs -> if p x then return True else xs) (return False) m
295−any p (Stream step state) = go state
297+any p (Stream step state) = go SPEC state
296 where
298 where
297− go st = do
299+ go !_ st = do
298 r <- step defState st
300 r <- step defState st
299 case r of
301 case r of
300 Yield x s
302 Yield x s
301− | p x -> return True
303+ | p x -> return True
302− | otherwise -> go s
304+ | otherwise -> go SPEC s
303− Skip s -> go s
305+ Skip s -> go SPEC s
304 Stop -> return False
306 Stop -> return False
305
307
306{-# INLINE_NORMAL maximum #-}
308{-# INLINE_NORMAL maximum #-}
307maximum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
309maximum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
308−maximum (Stream step state) = go Nothing state
310+maximum (Stream step state) = go SPEC Nothing' state
309 where
311 where
310− go Nothing st = do
312+ go !_ Nothing' st = do
311 r <- step defState st
313 r <- step defState st
312 case r of
314 case r of
313− Yield x s -> go (Just x) s
315+ Yield x s -> go SPEC (Just' x) s
314− Skip s -> go Nothing s
316+ Skip s -> go SPEC Nothing' s
315 Stop -> return Nothing
317 Stop -> return Nothing
316− go (Just acc) st = do
318+ go !_ (Just' acc) st = do
317 r <- step defState st
319 r <- step defState st
318 case r of
320 case r of
319 Yield x s
321 Yield x s
320− | acc <= x -> go (Just x) s
322+ | acc <= x -> go SPEC (Just' x) s
321− | otherwise -> go (Just acc) s
323+ | otherwise -> go SPEC (Just' acc) s
322− Skip s -> go (Just acc) s
324+ Skip s -> go SPEC (Just' acc) s
323 Stop -> return (Just acc)
325 Stop -> return (Just acc)
324
326
325{-# INLINE_NORMAL maximumBy #-}
327{-# INLINE_NORMAL maximumBy #-}
326maximumBy :: Monad m => (a -> a -> Ordering) -> Stream m a -> m (Maybe a)
328maximumBy :: Monad m => (a -> a -> Ordering) -> Stream m a -> m (Maybe a)
327−maximumBy cmp (Stream step state) = go Nothing state
329+maximumBy cmp (Stream step state) = go SPEC Nothing' state
328 where
330 where
329− go Nothing st = do
331+ go !_ Nothing' st = do
330 r <- step defState st
332 r <- step defState st
331 case r of
333 case r of
332− Yield x s -> go (Just x) s
334+ Yield x s -> go SPEC (Just' x) s
333− Skip s -> go Nothing s
335+ Skip s -> go SPEC Nothing' s
334 Stop -> return Nothing
336 Stop -> return Nothing
335− go (Just acc) st = do
337+ go !_ (Just' acc) st = do
336 r <- step defState st
338 r <- step defState st
337 case r of
339 case r of
338 Yield x s -> case cmp acc x of
340 Yield x s -> case cmp acc x of
339− GT -> go (Just acc) s
341+ GT -> go SPEC (Just' acc) s
340− _ -> go (Just x) s
342+ _ -> go SPEC (Just' x) s
341− Skip s -> go (Just acc) s
343+ Skip s -> go SPEC (Just' acc) s
342 Stop -> return (Just acc)
344 Stop -> return (Just acc)
343
345
344{-# INLINE_NORMAL minimum #-}
346{-# INLINE_NORMAL minimum #-}
345minimum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
347minimum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
346−minimum (Stream step state) = go Nothing state
348+minimum (Stream step state) = go SPEC Nothing' state
349+
347− where
350+ where
351+
348− go Nothing st = do
352+ go !_ Nothing' st = do
349 r <- step defState st
353 r <- step defState st
350 case r of
354 case r of
351− Yield x s -> go (Just x) s
355+ Yield x s -> go SPEC (Just' x) s
352− Skip s -> go Nothing s
356+ Skip s -> go SPEC Nothing' s
353 Stop -> return Nothing
357 Stop -> return Nothing
354− go (Just acc) st = do
358+ go !_ (Just' acc) st = do
355 r <- step defState st
359 r <- step defState st
356 case r of
360 case r of
357 Yield x s
361 Yield x s
358− | acc <= x -> go (Just acc) s
362+ | acc <= x -> go SPEC (Just' acc) s
359− | otherwise -> go (Just x) s
363+ | otherwise -> go SPEC (Just' x) s
360− Skip s -> go (Just acc) s
364+ Skip s -> go SPEC (Just' acc) s
361 Stop -> return (Just acc)
365 Stop -> return (Just acc)
362
366
363{-# INLINE_NORMAL minimumBy #-}
367{-# INLINE_NORMAL minimumBy #-}
364minimumBy :: Monad m => (a -> a -> Ordering) -> Stream m a -> m (Maybe a)
368minimumBy :: Monad m => (a -> a -> Ordering) -> Stream m a -> m (Maybe a)
365−minimumBy cmp (Stream step state) = go Nothing state
369+minimumBy cmp (Stream step state) = go SPEC Nothing' state
370+
366− where
371+ where
372+
367− go Nothing st = do
373+ go !_ Nothing' st = do
368 r <- step defState st
374 r <- step defState st
369 case r of
375 case r of
370− Yield x s -> go (Just x) s
376+ Yield x s -> go SPEC (Just' x) s
371− Skip s -> go Nothing s
377+ Skip s -> go SPEC Nothing' s
372 Stop -> return Nothing
378 Stop -> return Nothing
373− go (Just acc) st = do
379+ go !_ (Just' acc) st = do
374 r <- step defState st
380 r <- step defState st
375 case r of
381 case r of
376 Yield x s -> case cmp acc x of
382 Yield x s -> case cmp acc x of
377− GT -> go (Just x) s
383+ GT -> go SPEC (Just' x) s
378− _ -> go (Just acc) s
384+ _ -> go SPEC (Just' acc) s
379− Skip s -> go (Just acc) s
385+ Skip s -> go SPEC (Just' acc) s
380 Stop -> return (Just acc)
386 Stop -> return (Just acc)
381
387
382{-# INLINE_NORMAL (!!) #-}
388{-# INLINE_NORMAL (!!) #-}
383(!!) :: (Monad m) => Stream m a -> Int -> m (Maybe a)
389(!!) :: (Monad m) => Stream m a -> Int -> m (Maybe a)
384−(Stream step state) !! i = go i state
390+(Stream step state) !! i = go SPEC i state
391+
385− where
392+ where
393+
386− go n st = do
394+ go !_ !n st = do
387 r <- step defState st
395 r <- step defState st
388 case r of
396 case r of
389 Yield x s | n < 0 -> return Nothing
397 Yield x s | n < 0 -> return Nothing
390 | n == 0 -> return $ Just x
398 | n == 0 -> return $ Just x
391− | otherwise -> go (n - 1) s
399+ | otherwise -> go SPEC (n - 1) s
392− Skip s -> go n s
400+ Skip s -> go SPEC n s
393 Stop -> return Nothing
401 Stop -> return Nothing
394
402
395{-# INLINE_NORMAL lookup #-}
403{-# INLINE_NORMAL lookup #-}
core/src/Streamly/Internal/Data/Stream/StreamD/Type.hs+5−3
@@ -159,13 +159,13 @@ consM m (Stream step state) = Stream step1 Nothing
159-- | Does not fuse, has the same performance as the StreamK version.
159-- | Does not fuse, has the same performance as the StreamK version.
160{-# INLINE_NORMAL uncons #-}
160{-# INLINE_NORMAL uncons #-}
161uncons :: Monad m => Stream m a -> m (Maybe (a, Stream m a))
161uncons :: Monad m => Stream m a -> m (Maybe (a, Stream m a))
162−uncons (UnStream step state) = go state
162+uncons (UnStream step state) = go SPEC state
163 where
163 where
164− go st = do
164+ go !_ st = do
165 r <- step defState st
165 r <- step defState st
166 case r of
166 case r of
167 Yield x s -> return $ Just (x, Stream step s)
167 Yield x s -> return $ Just (x, Stream step s)
168− Skip s -> go s
168+ Skip s -> go SPEC s
169 Stop -> return Nothing
169 Stop -> return Nothing
170
170
171------------------------------------------------------------------------------
171------------------------------------------------------------------------------
@@ -373,6 +373,8 @@ foldrMx fstep final convert (Stream step state) = convert $ go SPEC state
373 Skip s -> go SPEC s
373 Skip s -> go SPEC s
374 Stop -> final
374 Stop -> final
375
375
376+-- XXX Should we make all argument strict wherever we use SPEC?
377+
376-- Note that foldr works on pure values, therefore it becomes necessarily
378-- Note that foldr works on pure values, therefore it becomes necessarily
377-- strict when the monad m is strict. In that case it cannot terminate early,
379-- strict when the monad m is strict. In that case it cannot terminate early,
378-- it would evaluate all of its input. Though, this should work fine with lazy
380-- it would evaluate all of its input. Though, this should work fine with lazy