From b5a28065646d86a9251f06db08ca55631263d5ad Mon Sep 17 00:00:00 2001 From: Alexey Khudyakov Date: Fri, 9 Jan 2026 20:02:44 +0300 Subject: [PATCH 1/4] Replace explcit seq with bang patterns for readability --- .../src/Data/Vector/Fusion/Bundle/Monadic.hs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/vector/src/Data/Vector/Fusion/Bundle/Monadic.hs b/vector/src/Data/Vector/Fusion/Bundle/Monadic.hs index 6e51532f..9f17e678 100644 --- a/vector/src/Data/Vector/Fusion/Bundle/Monadic.hs +++ b/vector/src/Data/Vector/Fusion/Bundle/Monadic.hs @@ -750,7 +750,7 @@ scanl' f = scanlM' (\a b -> return (f a b)) -- | Haskell-style scan with strict accumulator and a monadic operator scanlM' :: Monad m => (a -> b -> m a) -> a -> Bundle m v b -> Bundle m v a {-# INLINE scanlM' #-} -scanlM' f z s = z `seq` (z `cons` postscanlM f z s) +scanlM' f !z s = z `cons` postscanlM f z s -- | Initial-value free scan over a 'Bundle' scanl1 :: Monad m => (a -> a -> a) -> Bundle m v a -> Bundle m v a @@ -800,7 +800,7 @@ enumFromTo x y = fromList [x .. y] -- FIXME: add "too large" test for Int enumFromTo_small :: (Integral a, Monad m) => a -> a -> Bundle m v a {-# INLINE_FUSED enumFromTo_small #-} -enumFromTo_small x y = x `seq` y `seq` fromStream (Stream step (Just x)) (Exact n) +enumFromTo_small !x !y = fromStream (Stream step (Just x)) (Exact n) where n = delay_inline max (fromIntegral y - fromIntegral x + 1) 0 @@ -852,7 +852,7 @@ enumFromTo_small x y = x `seq` y `seq` fromStream (Stream step (Just x)) (Exact enumFromTo_int :: forall m v. (HasCallStack, Monad m) => Int -> Int -> Bundle m v Int {-# INLINE_FUSED enumFromTo_int #-} -enumFromTo_int x y = x `seq` y `seq` fromStream (Stream step (Just x)) (Exact (len x y)) +enumFromTo_int !x !y = fromStream (Stream step (Just x)) (Exact (len x y)) where {-# INLINE [0] len #-} len :: HasCallStack => Int -> Int -> Int @@ -869,7 +869,7 @@ enumFromTo_int x y = x `seq` y `seq` fromStream (Stream step (Just x)) (Exact (l enumFromTo_intlike :: forall m v a. (HasCallStack, Integral a, Monad m) => a -> a -> Bundle m v a {-# INLINE_FUSED enumFromTo_intlike #-} -enumFromTo_intlike x y = x `seq` y `seq` fromStream (Stream step (Just x)) (Exact (len x y)) +enumFromTo_intlike !x !y = fromStream (Stream step (Just x)) (Exact (len x y)) where {-# INLINE [0] len #-} len :: HasCallStack => a -> a -> Int @@ -907,7 +907,7 @@ enumFromTo_intlike x y = x `seq` y `seq` fromStream (Stream step (Just x)) (Exac enumFromTo_big_word :: forall m v a. (HasCallStack, Integral a, Monad m) => a -> a -> Bundle m v a {-# INLINE_FUSED enumFromTo_big_word #-} -enumFromTo_big_word x y = x `seq` y `seq` fromStream (Stream step (Just x)) (Exact (len x y)) +enumFromTo_big_word !x !y = fromStream (Stream step (Just x)) (Exact (len x y)) where {-# INLINE [0] len #-} len :: HasCallStack => a -> a -> Int @@ -951,7 +951,7 @@ enumFromTo_big_word x y = x `seq` y `seq` fromStream (Stream step (Just x)) (Exa -- FIXME: the "too large" test is totally wrong enumFromTo_big_int :: forall m v a. (HasCallStack, Integral a, Monad m) => a -> a -> Bundle m v a {-# INLINE_FUSED enumFromTo_big_int #-} -enumFromTo_big_int x y = x `seq` y `seq` fromStream (Stream step (Just x)) (Exact (len x y)) +enumFromTo_big_int !x !y = fromStream (Stream step (Just x)) (Exact (len x y)) where {-# INLINE [0] len #-} len :: HasCallStack => a -> a -> Int @@ -980,7 +980,7 @@ enumFromTo_big_int x y = x `seq` y `seq` fromStream (Stream step (Just x)) (Exac enumFromTo_char :: Monad m => Char -> Char -> Bundle m v Char {-# INLINE_FUSED enumFromTo_char #-} -enumFromTo_char x y = x `seq` y `seq` fromStream (Stream step xn) (Exact n) +enumFromTo_char !x !y = fromStream (Stream step xn) (Exact n) where xn = ord x yn = ord y @@ -1005,7 +1005,7 @@ enumFromTo_char x y = x `seq` y `seq` fromStream (Stream step xn) (Exact n) enumFromTo_double :: forall m v a. (HasCallStack, Monad m, Ord a, RealFrac a) => a -> a -> Bundle m v a {-# INLINE_FUSED enumFromTo_double #-} -enumFromTo_double n m = n `seq` m `seq` fromStream (Stream step ini) (Max (len n lim)) +enumFromTo_double !n !m = fromStream (Stream step ini) (Max (len n lim)) where lim = m + 1/2 -- important to float out @@ -1071,7 +1071,7 @@ unsafeFromList sz xs = fromStream (S.fromList xs) sz fromVector :: (Monad m, Vector v a) => v a -> Bundle m v a {-# INLINE_FUSED fromVector #-} -fromVector v = v `seq` n `seq` Bundle (Stream step 0) +fromVector !v = n `seq` Bundle (Stream step 0) (Stream vstep True) (Just v) (Exact n) From 71c83f10ce88ba7ab3ec456f21d5a0a55069a33f Mon Sep 17 00:00:00 2001 From: Alexey Khudyakov Date: Sun, 11 Jan 2026 13:14:54 +0300 Subject: [PATCH 2/4] Simplify all unconditional rewrites for enumFromTo --- .../src/Data/Vector/Fusion/Bundle/Monadic.hs | 60 +++++-------------- 1 file changed, 16 insertions(+), 44 deletions(-) diff --git a/vector/src/Data/Vector/Fusion/Bundle/Monadic.hs b/vector/src/Data/Vector/Fusion/Bundle/Monadic.hs index 9f17e678..83a2e0d1 100644 --- a/vector/src/Data/Vector/Fusion/Bundle/Monadic.hs +++ b/vector/src/Data/Vector/Fusion/Bundle/Monadic.hs @@ -7,6 +7,7 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeApplications #-} -- | -- Module : Data.Vector.Fusion.Bundle.Monadic -- Copyright : (c) Roman Leshchinskiy 2008-2010 @@ -810,21 +811,6 @@ enumFromTo_small !x !y = fromStream (Stream step (Just x)) (Exact n) | z < y = return $ Yield z (Just (z+1)) | otherwise = return $ Done -{-# RULES - -"enumFromTo [Bundle]" - enumFromTo = enumFromTo_small :: Monad m => Int8 -> Int8 -> Bundle m v Int8 - -"enumFromTo [Bundle]" - enumFromTo = enumFromTo_small :: Monad m => Int16 -> Int16 -> Bundle m v Int16 - -"enumFromTo [Bundle]" - enumFromTo = enumFromTo_small :: Monad m => Word8 -> Word8 -> Bundle m v Word8 - -"enumFromTo [Bundle]" - enumFromTo = enumFromTo_small :: Monad m => Word16 -> Word16 -> Bundle m v Word16 #-} - - #if WORD_SIZE_IN_BITS > 32 @@ -887,10 +873,6 @@ enumFromTo_intlike !x !y = fromStream (Stream step (Just x)) (Exact (len x y)) | otherwise = return $ Done {-# RULES - -"enumFromTo [Bundle]" - enumFromTo = enumFromTo_int :: Monad m => Int -> Int -> Bundle m v Int - #if WORD_SIZE_IN_BITS > 32 "enumFromTo [Bundle]" @@ -900,7 +882,6 @@ enumFromTo_intlike !x !y = fromStream (Stream step (Just x)) (Exact (len x y)) "enumFromTo [Bundle]" enumFromTo = enumFromTo_intlike :: Monad m => Int32 -> Int32 -> Bundle m v Int32 #-} - #endif @@ -926,13 +907,6 @@ enumFromTo_big_word !x !y = fromStream (Stream step (Just x)) (Exact (len x y)) {-# RULES -"enumFromTo [Bundle]" - enumFromTo = enumFromTo_big_word :: Monad m => Word -> Word -> Bundle m v Word - -"enumFromTo [Bundle]" - enumFromTo = enumFromTo_big_word - :: Monad m => Word64 -> Word64 -> Bundle m v Word64 - #if WORD_SIZE_IN_BITS == 32 "enumFromTo [Bundle]" @@ -940,10 +914,7 @@ enumFromTo_big_word !x !y = fromStream (Stream step (Just x)) (Exact (len x y)) :: Monad m => Word32 -> Word32 -> Bundle m v Word32 #endif - -"enumFromTo [Bundle]" - enumFromTo = enumFromTo_big_word - :: Monad m => Integer -> Integer -> Bundle m v Integer #-} + #-} #if WORD_SIZE_IN_BITS > 32 @@ -974,8 +945,6 @@ enumFromTo_big_int !x !y = fromStream (Stream step (Just x)) (Exact (len x y)) "enumFromTo [Bundle]" enumFromTo = enumFromTo_big_int :: Monad m => Int64 -> Int64 -> Bundle m v Int64 #-} - - #endif enumFromTo_char :: Monad m => Char -> Char -> Bundle m v Char @@ -991,11 +960,6 @@ enumFromTo_char !x !y = fromStream (Stream step xn) (Exact n) step zn | zn <= yn = return $ Yield (unsafeChr zn) (zn+1) | otherwise = return $ Done -{-# RULES - -"enumFromTo [Bundle]" - enumFromTo = enumFromTo_char #-} - ------------------------------------------------------------------------ @@ -1025,12 +989,20 @@ enumFromTo_double !n !m = fromStream (Stream step ini) (Max (len n lim)) x' = x + n {-# RULES - -"enumFromTo [Bundle]" - enumFromTo = enumFromTo_double :: Monad m => Double -> Double -> Bundle m v Double - -"enumFromTo [Bundle]" - enumFromTo = enumFromTo_double :: Monad m => Float -> Float -> Bundle m v Float #-} +"enumFromTo [Bundle]" enumFromTo @Int8 = enumFromTo_small +"enumFromTo [Bundle]" enumFromTo @Int16 = enumFromTo_small +"enumFromTo [Bundle]" enumFromTo @Word8 = enumFromTo_small +"enumFromTo [Bundle]" enumFromTo @Word16 = enumFromTo_small + +"enumFromTo [Bundle]" enumFromTo @Int = enumFromTo_int +"enumFromTo [Bundle]" enumFromTo @Word = enumFromTo_big_word +"enumFromTo [Bundle]" enumFromTo @Word64 = enumFromTo_big_word +"enumFromTo [Bundle]" enumFromTo @Integer = enumFromTo_big_word + +"enumFromTo [Bundle]" enumFromTo @Char = enumFromTo_char +"enumFromTo [Bundle]" enumFromTo @Double = enumFromTo_double +"enumFromTo [Bundle]" enumFromTo @Float = enumFromTo_double + #-} From 2667478ce3dc0405452d50e29fc07d046588a9d4 Mon Sep 17 00:00:00 2001 From: Alexey Khudyakov Date: Sun, 11 Jan 2026 13:25:19 +0300 Subject: [PATCH 3/4] Put enumFromTo rules to one place except one for Int64 --- .../src/Data/Vector/Fusion/Bundle/Monadic.hs | 48 ++++++------------- 1 file changed, 14 insertions(+), 34 deletions(-) diff --git a/vector/src/Data/Vector/Fusion/Bundle/Monadic.hs b/vector/src/Data/Vector/Fusion/Bundle/Monadic.hs index 83a2e0d1..68e87bba 100644 --- a/vector/src/Data/Vector/Fusion/Bundle/Monadic.hs +++ b/vector/src/Data/Vector/Fusion/Bundle/Monadic.hs @@ -812,18 +812,6 @@ enumFromTo_small !x !y = fromStream (Stream step (Just x)) (Exact n) | otherwise = return $ Done -#if WORD_SIZE_IN_BITS > 32 - -{-# RULES - -"enumFromTo [Bundle]" - enumFromTo = enumFromTo_small :: Monad m => Int32 -> Int32 -> Bundle m v Int32 - -"enumFromTo [Bundle]" - enumFromTo = enumFromTo_small :: Monad m => Word32 -> Word32 -> Bundle m v Word32 #-} - -#endif - -- NOTE: We could implement a generic "too large" test: -- -- len x y | x > y = 0 @@ -872,17 +860,6 @@ enumFromTo_intlike !x !y = fromStream (Stream step (Just x)) (Exact (len x y)) | z < y = return $ Yield z (Just (z+1)) | otherwise = return $ Done -{-# RULES -#if WORD_SIZE_IN_BITS > 32 - -"enumFromTo [Bundle]" - enumFromTo = enumFromTo_intlike :: Monad m => Int64 -> Int64 -> Bundle m v Int64 #-} - -#else - -"enumFromTo [Bundle]" - enumFromTo = enumFromTo_intlike :: Monad m => Int32 -> Int32 -> Bundle m v Int32 #-} -#endif @@ -905,16 +882,6 @@ enumFromTo_big_word !x !y = fromStream (Stream step (Just x)) (Exact (len x y)) | z < y = return $ Yield z (Just (z+1)) | otherwise = return $ Done -{-# RULES - -#if WORD_SIZE_IN_BITS == 32 - -"enumFromTo [Bundle]" - enumFromTo = enumFromTo_big_word - :: Monad m => Word32 -> Word32 -> Bundle m v Word32 - -#endif - #-} #if WORD_SIZE_IN_BITS > 32 @@ -1004,7 +971,20 @@ enumFromTo_double !n !m = fromStream (Stream step ini) (Max (len n lim)) "enumFromTo [Bundle]" enumFromTo @Float = enumFromTo_double #-} - +#if WORD_SIZE_IN_BITS > 32 +-- 64bit systems +{-# RULES +"enumFromTo [Bundle]" enumFromTo @Int32 = enumFromTo_small +"enumFromTo [Bundle]" enumFromTo @Int64 = enumFromTo_intlike +"enumFromTo [Bundle]" enumFromTo @Word32 = enumFromTo_small + #-} +#else +-- 32bit systems +{-# RULES +"enumFromTo [Bundle]" enumFromTo @Int32 = enumFromTo_intlike +"enumFromTo [Bundle]" enumFromTo @Word32 = enumFromTo_big_word + #-} +#endif ------------------------------------------------------------------------ From 29ba9a6ebefb3e2e49ad9c7a3382b1571cf0ea65 Mon Sep 17 00:00:00 2001 From: Alexey Khudyakov Date: Sun, 11 Jan 2026 13:33:15 +0300 Subject: [PATCH 4/4] Fix rule for Int64 for 32-bit platforms Note that #ifdef condition was wrong! We had 2 rules on 64 bits and none at 32 bit. Lesson: #ifdef spaghetti is bad. It's better to keep conditions few and local. --- vector/src/Data/Vector/Fusion/Bundle/Monadic.hs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/vector/src/Data/Vector/Fusion/Bundle/Monadic.hs b/vector/src/Data/Vector/Fusion/Bundle/Monadic.hs index 68e87bba..ef70add4 100644 --- a/vector/src/Data/Vector/Fusion/Bundle/Monadic.hs +++ b/vector/src/Data/Vector/Fusion/Bundle/Monadic.hs @@ -884,8 +884,7 @@ enumFromTo_big_word !x !y = fromStream (Stream step (Just x)) (Exact (len x y)) -#if WORD_SIZE_IN_BITS > 32 - +#if WORD_SIZE_IN_BITS == 32 -- FIXME: the "too large" test is totally wrong enumFromTo_big_int :: forall m v a. (HasCallStack, Integral a, Monad m) => a -> a -> Bundle m v a {-# INLINE_FUSED enumFromTo_big_int #-} @@ -905,13 +904,6 @@ enumFromTo_big_int !x !y = fromStream (Stream step (Just x)) (Exact (len x y)) step (Just z) | z == y = return $ Yield z Nothing | z < y = return $ Yield z (Just (z+1)) | otherwise = return $ Done - - -{-# RULES - -"enumFromTo [Bundle]" - enumFromTo = enumFromTo_big_int :: Monad m => Int64 -> Int64 -> Bundle m v Int64 #-} - #endif enumFromTo_char :: Monad m => Char -> Char -> Bundle m v Char @@ -983,6 +975,7 @@ enumFromTo_double !n !m = fromStream (Stream step ini) (Max (len n lim)) {-# RULES "enumFromTo [Bundle]" enumFromTo @Int32 = enumFromTo_intlike "enumFromTo [Bundle]" enumFromTo @Word32 = enumFromTo_big_word +"enumFromTo [Bundle]" enumFromTo @Int64 = enumFromTo_big_int #-} #endif