Reexport scanl' (#74)

This is useful for the same reasons that foldl' is useful
This commit is contained in:
Moritz Kiefer
2017-12-18 19:03:45 +00:00
committed by Stephen Diehl
parent d462550f07
commit 2d8d1f3357
2 changed files with 41 additions and 0 deletions
+1
View File
@@ -781,6 +781,7 @@
* runStateT * runStateT
* scaleFloat * scaleFloat
* scanl * scanl
* scanl'
* scanr * scanr
* second * second
* selName * selName
+40
View File
@@ -1,3 +1,4 @@
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-} {-# LANGUAGE CPP #-}
{-# LANGUAGE Trustworthy #-} {-# LANGUAGE Trustworthy #-}
{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleContexts #-}
@@ -27,6 +28,7 @@ module Protolude (
liftIO2, liftIO2,
#if !MIN_VERSION_base(4,8,0) #if !MIN_VERSION_base(4,8,0)
(&), (&),
scanl',
#endif #endif
die, die,
) where ) where
@@ -177,6 +179,9 @@ import Data.List as X (
, subsequences , subsequences
, permutations , permutations
, scanl , scanl
#if MIN_VERSION_base(4,8,0)
, scanl'
#endif
, scanr , scanr
, iterate , iterate
, repeat , repeat
@@ -197,6 +202,12 @@ import Data.List as X (
, genericReplicate , genericReplicate
) )
#if !MIN_VERSION_base(4,8,0)
-- These imports are required for the scanl' rewrite rules
import GHC.Exts (build)
import Data.List (tail)
#endif
-- Hashing -- Hashing
import Data.Hashable as X ( import Data.Hashable as X (
Hashable Hashable
@@ -619,3 +630,32 @@ die err = System.Exit.die (toS err)
die :: Text -> IO a die :: Text -> IO a
die err = hPutStrLn stderr err >> exitFailure die err = hPutStrLn stderr err >> exitFailure
#endif #endif
#if !MIN_VERSION_base(4,8,0)
-- This is a literal copy of the implementation in GHC.List in base-4.10.1.0.
-- | A strictly accumulating version of 'scanl'
{-# NOINLINE [1] scanl' #-}
scanl' :: (b -> a -> b) -> b -> [a] -> [b]
scanl' = scanlGo'
where
scanlGo' :: (b -> a -> b) -> b -> [a] -> [b]
scanlGo' f !q ls = q : (case ls of
[] -> []
x:xs -> scanlGo' f (f q x) xs)
{-# RULES
"scanl'" [~1] forall f a bs . scanl' f a bs =
build (\c n -> a `c` foldr (scanlFB' f c) (flipSeqScanl' n) bs a)
"scanlList'" [1] forall f a bs .
foldr (scanlFB' f (:)) (flipSeqScanl' []) bs a = tail (scanl' f a bs)
#-}
{-# INLINE [0] scanlFB' #-}
scanlFB' :: (b -> a -> b) -> (b -> c -> c) -> a -> (b -> c) -> b -> c
scanlFB' f c = \b g -> \x -> let !b' = f x b in b' `c` g b'
{-# INLINE [0] flipSeqScanl' #-}
flipSeqScanl' :: a -> b -> a
flipSeqScanl' a !_b = a
#endif