@@ -50,6 +50,10 @@ module Streamly.Internal.Data.Fold
51 , variance
51 , variance
54+ , rollingHashWithSalt
55+ -- , rollingHashFirstN
56+ -- , rollingHashLastN
54 -- ** Full Folds (Monoidal)
58 -- ** Full Folds (Monoidal)
@@ -486,6 +490,45 @@ variance = Fold step (return begin) (return . done)
486stdDev :: (Monad m, Floating a) => Fold m a a
490stdDev :: (Monad m, Floating a) => Fold m a a
487stdDev = sqrt variance
491stdDev = sqrt variance
493+-- | Compute an 'Int' sized polynomial rolling hash
495+-- > H = salt * k ^ n + c1 * k ^ (n - 1) + c2 * k ^ (n - 2) + ... + cn * k ^ 0
497+-- Where @c1@, @c2@, @cn@ are the elements in the input stream and @k@ is a
500+-- This hash is often used in Rabin-Karp string search algorithm.
502+-- See https://en.wikipedia.org/wiki/Rolling_hash
505+{-# INLINABLE rollingHashWithSalt #-}
506+rollingHashWithSalt :: (Monad m, Enum a) => Int -> Fold m a Int
507+rollingHashWithSalt salt = Fold step initial extract
510+ initial = return salt
511+ step cksum a = return $ cksum * k + fromEnum a
514+-- | A default salt used in the implementation of 'rollingHash'.
515+{-# INLINE defaultSalt #-}
517+#if WORD_SIZE_IN_BITS == 64
518+defaultSalt = 0xdc36d1615b7400a4
520+defaultSalt = 0x087fc72c
523+-- | Compute an 'Int' sized polynomial rolling hash of a stream.
525+-- > rollingHash = rollingHashWithSalt defaultSalt
528+{-# INLINABLE rollingHash #-}
529+rollingHash :: (Monad m, Enum a) => Fold m a Int
530+rollingHash = rollingHashWithSalt defaultSalt
489------------------------------------------------------------------------------
532------------------------------------------------------------------------------
490-- Monoidal left folds
533-- Monoidal left folds
491------------------------------------------------------------------------------
534------------------------------------------------------------------------------