From 44e5d3bc488a92f6385307048c4838955b90f55d Mon Sep 17 00:00:00 2001 From: "Daniel.Winograd-Cort" Date: Sat, 13 Jan 2018 11:24:19 -0500 Subject: [PATCH 1/8] Added HasCallStack to partial functions --- containers/src/Data/IntMap/Internal.hs | 13 +++++----- containers/src/Data/IntSet/Internal.hs | 10 ++++---- containers/src/Data/Map/Internal.hs | 21 ++++++++-------- containers/src/Data/Map/Strict/Internal.hs | 4 +++- containers/src/Data/Sequence/Internal.hs | 28 ++++++++++++---------- containers/src/Data/Set/Internal.hs | 16 +++++++------ 6 files changed, 51 insertions(+), 41 deletions(-) diff --git a/containers/src/Data/IntMap/Internal.hs b/containers/src/Data/IntMap/Internal.hs index 6cd047625..c86c24a11 100644 --- a/containers/src/Data/IntMap/Internal.hs +++ b/containers/src/Data/IntMap/Internal.hs @@ -364,6 +364,7 @@ import Text.Read #endif import qualified Control.Category as Category +import GHC.Stack (HasCallStack) {-------------------------------------------------------------------- Types @@ -429,7 +430,7 @@ deriving instance Lift a => Lift (IntMap a) -- > fromList [(5,'a'), (3,'b')] ! 1 Error: element not in the map -- > fromList [(5,'a'), (3,'b')] ! 5 == 'a' -(!) :: IntMap a -> Key -> a +(!) :: HasCallStack => IntMap a -> Key -> a (!) m k = find k m -- | \(O(\min(n,W))\). Find the value at a key. @@ -649,7 +650,7 @@ lookup !k = go go Nil = Nothing -- See Note: Local 'go' functions and capturing] -find :: Key -> IntMap a -> a +find :: HasCallStack => Key -> IntMap a -> a find !k = go where go (Bin p l r) | left k p = go l @@ -2351,7 +2352,7 @@ minView t = fmap (\((_, x), t') -> (x, t')) (minViewWithKey t) -- Calls 'error' if the map is empty. -- -- __Note__: This function is partial. Prefer 'maxViewWithKey'. -deleteFindMax :: IntMap a -> ((Key, a), IntMap a) +deleteFindMax :: HasCallStack => IntMap a -> ((Key, a), IntMap a) deleteFindMax = fromMaybe (error "deleteFindMax: empty map has no maximal element") . maxViewWithKey -- | \(O(\min(n,W))\). Delete and find the minimal element. @@ -2359,7 +2360,7 @@ deleteFindMax = fromMaybe (error "deleteFindMax: empty map has no maximal elemen -- Calls 'error' if the map is empty. -- -- __Note__: This function is partial. Prefer 'minViewWithKey'. -deleteFindMin :: IntMap a -> ((Key, a), IntMap a) +deleteFindMin :: HasCallStack => IntMap a -> ((Key, a), IntMap a) deleteFindMin = fromMaybe (error "deleteFindMin: empty map has no minimal element") . minViewWithKey -- The KeyValue type is used when returning a key-value pair and helps with @@ -2394,7 +2395,7 @@ lookupMin (Bin p l r) = -- | \(O(\min(n,W))\). The minimal key of the map. Calls 'error' if the map is empty. -- -- __Note__: This function is partial. Prefer 'lookupMin'. -findMin :: IntMap a -> (Key, a) +findMin :: HasCallStack => IntMap a -> (Key, a) findMin t | Just r <- lookupMin t = r | otherwise = error "findMin: empty map has no minimal element" @@ -2415,7 +2416,7 @@ lookupMax (Bin p l r) = -- | \(O(\min(n,W))\). The maximal key of the map. Calls 'error' if the map is empty. -- -- __Note__: This function is partial. Prefer 'lookupMax'. -findMax :: IntMap a -> (Key, a) +findMax :: HasCallStack => IntMap a -> (Key, a) findMax t | Just r <- lookupMax t = r | otherwise = error "findMax: empty map has no maximal element" diff --git a/containers/src/Data/IntSet/Internal.hs b/containers/src/Data/IntSet/Internal.hs index 9008244e3..e09597da4 100644 --- a/containers/src/Data/IntSet/Internal.hs +++ b/containers/src/Data/IntSet/Internal.hs @@ -234,6 +234,8 @@ import Language.Haskell.TH () import qualified Data.Foldable as Foldable import Data.Functor.Identity (Identity(..)) +import GHC.Stack (HasCallStack) + infixl 9 \\{-This comment teaches CPP correct behaviour -} {-------------------------------------------------------------------- @@ -1103,7 +1105,7 @@ minView t = -- Calls 'error' if the set is empty. -- -- __Note__: This function is partial. Prefer 'minView'. -deleteFindMin :: IntSet -> (Key, IntSet) +deleteFindMin :: HasCallStack => IntSet -> (Key, IntSet) deleteFindMin = fromMaybe (error "deleteFindMin: empty set has no minimal element") . minView -- | \(O(\min(n,W))\). Delete and find the maximal element. @@ -1111,7 +1113,7 @@ deleteFindMin = fromMaybe (error "deleteFindMin: empty set has no minimal elemen -- Calls 'error' if the set is empty. -- -- __Note__: This function is partial. Prefer 'maxView'. -deleteFindMax :: IntSet -> (Key, IntSet) +deleteFindMax :: HasCallStack => IntSet -> (Key, IntSet) deleteFindMax = fromMaybe (error "deleteFindMax: empty set has no maximal element") . maxView lookupMinSure :: IntSet -> Key @@ -1133,7 +1135,7 @@ lookupMin (Bin p l r) = Just $! lookupMinSure (if signBranch p then r else l) -- is empty. -- -- __Note__: This function is partial. Prefer 'lookupMin'. -findMin :: IntSet -> Key +findMin :: HasCallStack => IntSet -> Key findMin t | Just r <- lookupMin t = r | otherwise = error "findMin: empty set has no minimal element" @@ -1157,7 +1159,7 @@ lookupMax (Bin p l r) = Just $! lookupMaxSure (if signBranch p then l else r) -- is empty. -- -- __Note__: This function is partial. Prefer 'lookupMax'. -findMax :: IntSet -> Key +findMax :: HasCallStack => IntSet -> Key findMax t | Just r <- lookupMax t = r | otherwise = error "findMax: empty set has no maximal element" diff --git a/containers/src/Data/Map/Internal.hs b/containers/src/Data/Map/Internal.hs index 40181416f..210b23ff1 100644 --- a/containers/src/Data/Map/Internal.hs +++ b/containers/src/Data/Map/Internal.hs @@ -426,6 +426,7 @@ import Data.Coerce import Text.Read hiding (lift) #endif import qualified Control.Category as Category +import GHC.Stack (HasCallStack) {-------------------------------------------------------------------- Operators @@ -440,7 +441,7 @@ infixl 9 !,!?,\\ -- -- > fromList [(5,'a'), (3,'b')] ! 1 Error: element not in the map -- > fromList [(5,'a'), (3,'b')] ! 5 == 'a' -(!) :: Ord k => Map k a -> k -> a +(!) :: (HasCallStack, Ord k) => Map k a -> k -> a (!) m k = find k m #if __GLASGOW_HASKELL__ {-# INLINE (!) #-} @@ -1484,7 +1485,7 @@ alterFYoneda = go -- > findIndex 6 (fromList [(5,"a"), (3,"b")]) Error: element is not in the map -- See Note: Type of local 'go' function -findIndex :: Ord k => k -> Map k a -> Int +findIndex :: (HasCallStack, Ord k) => k -> Map k a -> Int findIndex = go 0 where go :: Ord k => Int -> k -> Map k a -> Int @@ -1530,7 +1531,7 @@ lookupIndex = go 0 -- > elemAt 1 (fromList [(5,"a"), (3,"b")]) == (5, "a") -- > elemAt 2 (fromList [(5,"a"), (3,"b")]) Error: index out of range -elemAt :: Int -> Map k a -> (k,a) +elemAt :: HasCallStack => Int -> Map k a -> (k,a) elemAt !_ Tip = error "Map.elemAt: index out of range" elemAt i (Bin _ kx x l r) = case compare i sizeL of @@ -1621,7 +1622,7 @@ splitAt i0 m0 -- > updateAt (\_ _ -> Nothing) 2 (fromList [(5,"a"), (3,"b")]) Error: index out of range -- > updateAt (\_ _ -> Nothing) (-1) (fromList [(5,"a"), (3,"b")]) Error: index out of range -updateAt :: (k -> a -> Maybe a) -> Int -> Map k a -> Map k a +updateAt :: HasCallStack => (k -> a -> Maybe a) -> Int -> Map k a -> Map k a updateAt f !i t = case t of Tip -> error "Map.updateAt: index out of range" @@ -1645,7 +1646,7 @@ updateAt f !i t = -- > deleteAt 2 (fromList [(5,"a"), (3,"b")]) Error: index out of range -- > deleteAt (-1) (fromList [(5,"a"), (3,"b")]) Error: index out of range -deleteAt :: Int -> Map k a -> Map k a +deleteAt :: HasCallStack => Int -> Map k a -> Map k a deleteAt !i t = case t of Tip -> error "Map.deleteAt: index out of range" @@ -1702,7 +1703,7 @@ lookupMin (Bin _ k x l _) = Just $! kvToTuple (lookupMinSure k x l) -- > findMin (fromList [(5,"a"), (3,"b")]) == (3,"b") -- > findMin empty Error: empty map has no minimal element -findMin :: Map k a -> (k,a) +findMin :: HasCallStack => Map k a -> (k,a) findMin t | Just r <- lookupMin t = r | otherwise = error "Map.findMin: empty map has no minimal element" @@ -1730,7 +1731,7 @@ lookupMax (Bin _ k x _ r) = Just $! kvToTuple (lookupMaxSure k x r) -- > findMax (fromList [(5,"a"), (3,"b")]) == (5,"a") -- > findMax empty Error: empty map has no maximal element -findMax :: Map k a -> (k,a) +findMax :: HasCallStack => Map k a -> (k,a) findMax t | Just r <- lookupMax t = r | otherwise = error "Map.findMax: empty map has no maximal element" @@ -2848,7 +2849,7 @@ mergeA -- @only2@ are 'id' and @'const' 'empty'@, but for example @'map' f@, -- @'filterWithKey' f@, or @'mapMaybeWithKey' f@ could be used for any @f@. -mergeWithKey :: Ord k +mergeWithKey :: (HasCallStack, Ord k) => (k -> a -> b -> Maybe c) -> (Map k a -> Map k c) -> (Map k b -> Map k c) @@ -4182,7 +4183,7 @@ maxViewSure !k x !l r = case r of -- Calls 'error' if the map is empty. -- -- __Note__: This function is partial. Prefer 'minViewWithKey'. -deleteFindMin :: Map k a -> ((k,a),Map k a) +deleteFindMin :: HasCallStack => Map k a -> ((k,a),Map k a) deleteFindMin t = case minViewWithKey t of Nothing -> (error "Map.deleteFindMin: can not return the minimal element of an empty map", Tip) Just res -> res @@ -4192,7 +4193,7 @@ deleteFindMin t = case minViewWithKey t of -- Calls 'error' if the map is empty. -- -- __Note__: This function is partial. Prefer 'maxViewWithKey'. -deleteFindMax :: Map k a -> ((k,a),Map k a) +deleteFindMax :: HasCallStack => Map k a -> ((k,a),Map k a) deleteFindMax t = case maxViewWithKey t of Nothing -> (error "Map.deleteFindMax: can not return the maximal element of an empty map", Tip) Just res -> res diff --git a/containers/src/Data/Map/Strict/Internal.hs b/containers/src/Data/Map/Strict/Internal.hs index d70977e38..2b89250df 100644 --- a/containers/src/Data/Map/Strict/Internal.hs +++ b/containers/src/Data/Map/Strict/Internal.hs @@ -424,6 +424,8 @@ import Data.Coerce import Data.Functor.Identity (Identity (..)) #endif +import GHC.Stack (HasCallStack) + import qualified Data.Foldable as Foldable -- [Note: Pointer equality for sharing] @@ -869,7 +871,7 @@ atKeyIdentity k f t = Identity $ atKeyPlain Strict k (coerce f) t -- > updateAt (\_ _ -> Nothing) 2 (fromList [(5,"a"), (3,"b")]) Error: index out of range -- > updateAt (\_ _ -> Nothing) (-1) (fromList [(5,"a"), (3,"b")]) Error: index out of range -updateAt :: (k -> a -> Maybe a) -> Int -> Map k a -> Map k a +updateAt :: HasCallStack => (k -> a -> Maybe a) -> Int -> Map k a -> Map k a updateAt f i t = i `seq` case t of Tip -> error "Map.updateAt: index out of range" diff --git a/containers/src/Data/Sequence/Internal.hs b/containers/src/Data/Sequence/Internal.hs index ac9796ab3..1dd34d5ac 100644 --- a/containers/src/Data/Sequence/Internal.hs +++ b/containers/src/Data/Sequence/Internal.hs @@ -235,6 +235,8 @@ import Utils.Containers.Internal.StrictPair (StrictPair (..), toPair) import Control.Monad.Zip (MonadZip (..)) import Control.Monad.Fix (MonadFix (..), fix) +import GHC.Stack (HasCallStack) + default () -- We define our own copy here, for Monoid only, even though this @@ -518,7 +520,7 @@ instance MonadFix Seq where -- This is just like the instance for lists, but we can take advantage of -- constant-time length and logarithmic-time indexing to speed things up. -- Using fromFunction, we make this about as lazy as we can. -mfixSeq :: (a -> Seq a) -> Seq a +mfixSeq :: HasCallStack => (a -> Seq a) -> Seq a mfixSeq f = fromFunction (length (f err)) (\k -> fix (\xk -> f xk `index` k)) where err = error "mfix for Data.Sequence.Seq applied to strict function" @@ -1764,7 +1766,7 @@ singleton x = Seq (Single (Elem x)) -- Calls 'error' if @n < 0@. -- -- __Note__: This function is partial. -replicate :: Int -> a -> Seq a +replicate :: HasCallStack => Int -> a -> Seq a replicate n x | n >= 0 = runIdentity (replicateA n (Identity x)) | otherwise = error "replicate takes a nonnegative integer argument" @@ -1777,7 +1779,7 @@ replicate n x -- __Note__: This function is partial. -- -- > replicateA n x = sequenceA (replicate n x) -replicateA :: Applicative f => Int -> f a -> f (Seq a) +replicateA :: (HasCallStack, Applicative f) => Int -> f a -> f (Seq a) replicateA n x | n >= 0 = Seq <$> applicativeTree n 1 (Elem <$> x) | otherwise = error "replicateA takes a nonnegative integer argument" @@ -1786,7 +1788,7 @@ replicateA n x -- | Synonym for 'replicateA'. -- -- This definition exists for backwards compatibility. -replicateM :: Applicative m => Int -> m a -> m (Seq a) +replicateM :: (HasCallStack, Applicative m) => Int -> m a -> m (Seq a) replicateM = replicateA -- | \(O(\log k)\). @'cycleTaking' k xs@ forms a sequence of length @k@ by @@ -1804,7 +1806,7 @@ replicateM = replicateA -- __Note__: This function is partial. -- -- @since 0.5.8 -cycleTaking :: Int -> Seq a -> Seq a +cycleTaking :: HasCallStack => Int -> Seq a -> Seq a cycleTaking n !_xs | n <= 0 = empty cycleTaking _n xs | null xs = error "cycleTaking cannot take a positive number of elements from an empty cycle." cycleTaking n xs = cycleNTimes reps xs >< take final xs @@ -2218,7 +2220,7 @@ unfoldl f = unfoldl' empty -- Calls 'error' if @n < 0@. -- -- __Note__: This function is partial. -iterateN :: Int -> (a -> a) -> a -> Seq a +iterateN :: HasCallStack => Int -> (a -> a) -> a -> Seq a iterateN n f x | n >= 0 = replicateA n (State (\ y -> (f y, y))) `execState` x | otherwise = error "iterateN takes a nonnegative integer argument" @@ -2401,7 +2403,7 @@ scanl f z0 xs = z0 <| snd (mapAccumL (\ x z -> let x' = f x z in (x', x')) z0 xs -- __Note__: This function is partial. -- -- > scanl1 f (fromList [x1, x2, ...]) = fromList [x1, x1 `f` x2, ...] -scanl1 :: (a -> a -> a) -> Seq a -> Seq a +scanl1 :: HasCallStack => (a -> a -> a) -> Seq a -> Seq a scanl1 f xs = case viewl xs of EmptyL -> error "scanl1 takes a nonempty sequence as an argument" x :< xs' -> scanl f x xs' @@ -2415,7 +2417,7 @@ scanr f z0 xs = snd (mapAccumR (\ z x -> let z' = f x z in (z', z')) z0 xs) |> z -- Calls 'error' if the sequence is empty. -- -- __Note__: This function is partial. -scanr1 :: (a -> a -> a) -> Seq a -> Seq a +scanr1 :: HasCallStack => (a -> a -> a) -> Seq a -> Seq a scanr1 f xs = case viewr xs of EmptyR -> error "scanr1 takes a nonempty sequence as an argument" xs' :> x -> scanr f x xs' @@ -2435,7 +2437,7 @@ scanr1 f xs = case viewr xs of -- element until the result is forced. It can therefore lead to a space -- leak if the result is stored, unforced, in another structure. To retrieve -- an element immediately without forcing it, use 'lookup' or '(!?)'. -index :: Seq a -> Int -> a +index :: HasCallStack => Seq a -> Int -> a index (Seq xs) i -- See note on unsigned arithmetic in splitAt | fromIntegral i < (fromIntegral (size xs) :: Word) = case lookupTree i xs of @@ -3407,7 +3409,7 @@ valid. -- __Note__: This function is partial. -- -- @since 0.5.6.2 -fromFunction :: Int -> (Int -> a) -> Seq a +fromFunction :: HasCallStack => Int -> (Int -> a) -> Seq a fromFunction len f | len < 0 = error "Data.Sequence.fromFunction called with negative len" | len == 0 = empty | otherwise = Seq $ create (lift_elem f) 1 0 len @@ -3989,7 +3991,7 @@ splitSuffixN i s pr m (Four a b c d) -- __Note__: This function is partial. -- -- @since 0.5.8 -chunksOf :: Int -> Seq a -> Seq (Seq a) +chunksOf :: HasCallStack => Int -> Seq a -> Seq (Seq a) chunksOf n xs | n <= 0 = if null xs then empty @@ -4986,7 +4988,7 @@ zipWith f s1 s2 = zipWith' f s1' s2' s2' = take minLen s2 -- | A version of zipWith that assumes the sequences have the same length. -zipWith' :: (a -> b -> c) -> Seq a -> Seq b -> Seq c +zipWith' :: HasCallStack => (a -> b -> c) -> Seq a -> Seq b -> Seq c zipWith' f s1 s2 = splitMap uncheckedSplitAt goLeaf s2 s1 where goLeaf (Seq (Single (Elem b))) a = f a b @@ -5031,7 +5033,7 @@ zipWith4 f s1 s2 s3 s4 = zipWith' ($) (zipWith3' f s1' s2' s3') s4' -- | fromList2, given a list and its length, constructs a completely -- balanced Seq whose elements are that list using the replicateA -- generalization. -fromList2 :: Int -> [a] -> Seq a +fromList2 :: HasCallStack => Int -> [a] -> Seq a fromList2 n = execState (replicateA n (State ht)) where ht (x:xs) = (xs, x) diff --git a/containers/src/Data/Set/Internal.hs b/containers/src/Data/Set/Internal.hs index 4682abc8c..82668ff21 100644 --- a/containers/src/Data/Set/Internal.hs +++ b/containers/src/Data/Set/Internal.hs @@ -258,6 +258,8 @@ import Language.Haskell.TH () import Data.Coerce (coerce) #endif +import GHC.Stack (HasCallStack) + {-------------------------------------------------------------------- Operators @@ -778,7 +780,7 @@ lookupMin (Bin _ x l _) = Just $! lookupMinSure x l -- empty. -- -- __Note__: This function is partial. Prefer 'lookupMin'. -findMin :: Set a -> a +findMin :: HasCallStack => Set a -> a findMin t | Just r <- lookupMin t = r | otherwise = error "Set.findMin: empty set has no minimal element" @@ -801,7 +803,7 @@ lookupMax (Bin _ x _ r) = Just $! lookupMaxSure x r -- empty. -- -- __Note__: This function is partial. Prefer 'lookupMax'. -findMax :: Set a -> a +findMax :: HasCallStack => Set a -> a findMax t | Just r <- lookupMax t = r | otherwise = error "Set.findMax: empty set has no maximal element" @@ -1457,7 +1459,7 @@ splitMember x (Bin _ y l r) -- @since 0.5.4 -- See Note: Type of local 'go' function -findIndex :: Ord a => a -> Set a -> Int +findIndex :: (HasCallStack, Ord a) => a -> Set a -> Int findIndex = go 0 where go :: Ord a => Int -> a -> Set a -> Int @@ -1507,7 +1509,7 @@ lookupIndex = go 0 -- -- @since 0.5.4 -elemAt :: Int -> Set a -> a +elemAt :: HasCallStack => Int -> Set a -> a elemAt !_ Tip = error "Set.elemAt: index out of range" elemAt i (Bin _ x l r) = case compare i sizeL of @@ -1530,7 +1532,7 @@ elemAt i (Bin _ x l r) -- -- @since 0.5.4 -deleteAt :: Int -> Set a -> Set a +deleteAt :: HasCallStack => Int -> Set a -> Set a deleteAt !i t = case t of Tip -> error "Set.deleteAt: index out of range" @@ -1828,7 +1830,7 @@ glue l@(Bin sl xl ll lr) r@(Bin sr xr rl rr) -- Calls 'error' if the set is empty. -- -- __Note__: This function is partial. Prefer 'minView'. -deleteFindMin :: Set a -> (a,Set a) +deleteFindMin :: HasCallStack => Set a -> (a,Set a) deleteFindMin t | Just r <- minView t = r | otherwise = (error "Set.deleteFindMin: can not return the minimal element of an empty set", Tip) @@ -1838,7 +1840,7 @@ deleteFindMin t -- Calls 'error' if the set is empty. -- -- __Note__: This function is partial. Prefer 'maxView'. -deleteFindMax :: Set a -> (a,Set a) +deleteFindMax :: HasCallStack => Set a -> (a,Set a) deleteFindMax t | Just r <- maxView t = r | otherwise = (error "Set.deleteFindMax: can not return the maximal element of an empty set", Tip) From 331e534c5221936f01ae8c012e036f85b40eb291 Mon Sep 17 00:00:00 2001 From: "Daniel.Winograd-Cort" Date: Sat, 13 Jan 2018 14:25:49 -0500 Subject: [PATCH 2/8] Added CPP to restrict to GHC>800 --- containers/src/Data/IntMap/Internal.hs | 30 ++++++++++++ containers/src/Data/IntSet/Internal.hs | 18 ++++++++ containers/src/Data/Map/Internal.hs | 42 +++++++++++++++++ containers/src/Data/Map/Strict/Internal.hs | 6 +++ containers/src/Data/Sequence/Internal.hs | 54 ++++++++++++++++++++++ containers/src/Data/Set/Internal.hs | 30 ++++++++++++ 6 files changed, 180 insertions(+) diff --git a/containers/src/Data/IntMap/Internal.hs b/containers/src/Data/IntMap/Internal.hs index c86c24a11..836408ad7 100644 --- a/containers/src/Data/IntMap/Internal.hs +++ b/containers/src/Data/IntMap/Internal.hs @@ -364,7 +364,9 @@ import Text.Read #endif import qualified Control.Category as Category +#if __GLASGOW_HASKELL__ >= 800 import GHC.Stack (HasCallStack) +#endif {-------------------------------------------------------------------- Types @@ -430,7 +432,11 @@ deriving instance Lift a => Lift (IntMap a) -- > fromList [(5,'a'), (3,'b')] ! 1 Error: element not in the map -- > fromList [(5,'a'), (3,'b')] ! 5 == 'a' +#if __GLASGOW_HASKELL__ >= 800 (!) :: HasCallStack => IntMap a -> Key -> a +#else +(!) :: IntMap a -> Key -> a +#endif (!) m k = find k m -- | \(O(\min(n,W))\). Find the value at a key. @@ -2352,7 +2358,11 @@ minView t = fmap (\((_, x), t') -> (x, t')) (minViewWithKey t) -- Calls 'error' if the map is empty. -- -- __Note__: This function is partial. Prefer 'maxViewWithKey'. +#if __GLASGOW_HASKELL__ >= 800 deleteFindMax :: HasCallStack => IntMap a -> ((Key, a), IntMap a) +#else +deleteFindMax :: IntMap a -> ((Key, a), IntMap a) +#endif deleteFindMax = fromMaybe (error "deleteFindMax: empty map has no maximal element") . maxViewWithKey -- | \(O(\min(n,W))\). Delete and find the minimal element. @@ -2360,7 +2370,11 @@ deleteFindMax = fromMaybe (error "deleteFindMax: empty map has no maximal elemen -- Calls 'error' if the map is empty. -- -- __Note__: This function is partial. Prefer 'minViewWithKey'. +#if __GLASGOW_HASKELL__ >= 800 deleteFindMin :: HasCallStack => IntMap a -> ((Key, a), IntMap a) +#else +deleteFindMin :: IntMap a -> ((Key, a), IntMap a) +#endif deleteFindMin = fromMaybe (error "deleteFindMin: empty map has no minimal element") . minViewWithKey -- The KeyValue type is used when returning a key-value pair and helps with @@ -2379,7 +2393,11 @@ kvToTuple :: KeyValue a -> (Key, a) kvToTuple (KeyValue k x) = (k, x) {-# INLINE kvToTuple #-} +#if __GLASGOW_HASKELL__ >= 800 +lookupMinSure :: HasCallStack => IntMap a -> KeyValue a +#else lookupMinSure :: IntMap a -> KeyValue a +#endif lookupMinSure (Tip k v) = KeyValue k v lookupMinSure (Bin _ l _) = lookupMinSure l lookupMinSure Nil = error "lookupMinSure Nil" @@ -2395,12 +2413,20 @@ lookupMin (Bin p l r) = -- | \(O(\min(n,W))\). The minimal key of the map. Calls 'error' if the map is empty. -- -- __Note__: This function is partial. Prefer 'lookupMin'. +#if __GLASGOW_HASKELL__ >= 800 findMin :: HasCallStack => IntMap a -> (Key, a) +#else +findMin :: IntMap a -> (Key, a) +#endif findMin t | Just r <- lookupMin t = r | otherwise = error "findMin: empty map has no minimal element" +#if __GLASGOW_HASKELL__ >= 800 +lookupMaxSure :: HasCallStack => IntMap a -> KeyValue a +#else lookupMaxSure :: IntMap a -> KeyValue a +#endif lookupMaxSure (Tip k v) = KeyValue k v lookupMaxSure (Bin _ _ r) = lookupMaxSure r lookupMaxSure Nil = error "lookupMaxSure Nil" @@ -2416,7 +2442,11 @@ lookupMax (Bin p l r) = -- | \(O(\min(n,W))\). The maximal key of the map. Calls 'error' if the map is empty. -- -- __Note__: This function is partial. Prefer 'lookupMax'. +#if __GLASGOW_HASKELL__ >= 800 findMax :: HasCallStack => IntMap a -> (Key, a) +#else +findMax :: IntMap a -> (Key, a) +#endif findMax t | Just r <- lookupMax t = r | otherwise = error "findMax: empty map has no maximal element" diff --git a/containers/src/Data/IntSet/Internal.hs b/containers/src/Data/IntSet/Internal.hs index e09597da4..2b49f8ac7 100644 --- a/containers/src/Data/IntSet/Internal.hs +++ b/containers/src/Data/IntSet/Internal.hs @@ -234,7 +234,9 @@ import Language.Haskell.TH () import qualified Data.Foldable as Foldable import Data.Functor.Identity (Identity(..)) +#if __GLASGOW_HASKELL__ >= 800 import GHC.Stack (HasCallStack) +#endif infixl 9 \\{-This comment teaches CPP correct behaviour -} @@ -1105,7 +1107,11 @@ minView t = -- Calls 'error' if the set is empty. -- -- __Note__: This function is partial. Prefer 'minView'. +#if __GLASGOW_HASKELL__ >= 800 deleteFindMin :: HasCallStack => IntSet -> (Key, IntSet) +#else +deleteFindMin :: IntSet -> (Key, IntSet) +#endif deleteFindMin = fromMaybe (error "deleteFindMin: empty set has no minimal element") . minView -- | \(O(\min(n,W))\). Delete and find the maximal element. @@ -1113,7 +1119,11 @@ deleteFindMin = fromMaybe (error "deleteFindMin: empty set has no minimal elemen -- Calls 'error' if the set is empty. -- -- __Note__: This function is partial. Prefer 'maxView'. +#if __GLASGOW_HASKELL__ >= 800 deleteFindMax :: HasCallStack => IntSet -> (Key, IntSet) +#else +deleteFindMax :: IntSet -> (Key, IntSet) +#endif deleteFindMax = fromMaybe (error "deleteFindMax: empty set has no maximal element") . maxView lookupMinSure :: IntSet -> Key @@ -1135,7 +1145,11 @@ lookupMin (Bin p l r) = Just $! lookupMinSure (if signBranch p then r else l) -- is empty. -- -- __Note__: This function is partial. Prefer 'lookupMin'. +#if __GLASGOW_HASKELL__ >= 800 findMin :: HasCallStack => IntSet -> Key +#else +findMin :: IntSet -> Key +#endif findMin t | Just r <- lookupMin t = r | otherwise = error "findMin: empty set has no minimal element" @@ -1159,7 +1173,11 @@ lookupMax (Bin p l r) = Just $! lookupMaxSure (if signBranch p then l else r) -- is empty. -- -- __Note__: This function is partial. Prefer 'lookupMax'. +#if __GLASGOW_HASKELL__ >= 800 findMax :: HasCallStack => IntSet -> Key +#else +findMax :: IntSet -> Key +#endif findMax t | Just r <- lookupMax t = r | otherwise = error "findMax: empty set has no maximal element" diff --git a/containers/src/Data/Map/Internal.hs b/containers/src/Data/Map/Internal.hs index 210b23ff1..873b9b088 100644 --- a/containers/src/Data/Map/Internal.hs +++ b/containers/src/Data/Map/Internal.hs @@ -426,7 +426,9 @@ import Data.Coerce import Text.Read hiding (lift) #endif import qualified Control.Category as Category +#if __GLASGOW_HASKELL__ >= 800 import GHC.Stack (HasCallStack) +#endif {-------------------------------------------------------------------- Operators @@ -441,7 +443,11 @@ infixl 9 !,!?,\\ -- -- > fromList [(5,'a'), (3,'b')] ! 1 Error: element not in the map -- > fromList [(5,'a'), (3,'b')] ! 5 == 'a' +#if __GLASGOW_HASKELL__ >= 800 (!) :: (HasCallStack, Ord k) => Map k a -> k -> a +#else +(!) :: Ord k => Map k a -> k -> a +#endif (!) m k = find k m #if __GLASGOW_HASKELL__ {-# INLINE (!) #-} @@ -1485,7 +1491,11 @@ alterFYoneda = go -- > findIndex 6 (fromList [(5,"a"), (3,"b")]) Error: element is not in the map -- See Note: Type of local 'go' function +#if __GLASGOW_HASKELL__ >= 800 findIndex :: (HasCallStack, Ord k) => k -> Map k a -> Int +#else +findIndex :: Ord k => k -> Map k a -> Int +#endif findIndex = go 0 where go :: Ord k => Int -> k -> Map k a -> Int @@ -1531,7 +1541,11 @@ lookupIndex = go 0 -- > elemAt 1 (fromList [(5,"a"), (3,"b")]) == (5, "a") -- > elemAt 2 (fromList [(5,"a"), (3,"b")]) Error: index out of range +#if __GLASGOW_HASKELL__ >= 800 elemAt :: HasCallStack => Int -> Map k a -> (k,a) +#else +elemAt :: Int -> Map k a -> (k,a) +#endif elemAt !_ Tip = error "Map.elemAt: index out of range" elemAt i (Bin _ kx x l r) = case compare i sizeL of @@ -1622,7 +1636,11 @@ splitAt i0 m0 -- > updateAt (\_ _ -> Nothing) 2 (fromList [(5,"a"), (3,"b")]) Error: index out of range -- > updateAt (\_ _ -> Nothing) (-1) (fromList [(5,"a"), (3,"b")]) Error: index out of range +#if __GLASGOW_HASKELL__ >= 800 updateAt :: HasCallStack => (k -> a -> Maybe a) -> Int -> Map k a -> Map k a +#else +updateAt :: (k -> a -> Maybe a) -> Int -> Map k a -> Map k a +#endif updateAt f !i t = case t of Tip -> error "Map.updateAt: index out of range" @@ -1646,7 +1664,11 @@ updateAt f !i t = -- > deleteAt 2 (fromList [(5,"a"), (3,"b")]) Error: index out of range -- > deleteAt (-1) (fromList [(5,"a"), (3,"b")]) Error: index out of range +#if __GLASGOW_HASKELL__ >= 800 deleteAt :: HasCallStack => Int -> Map k a -> Map k a +#else +deleteAt :: Int -> Map k a -> Map k a +#endif deleteAt !i t = case t of Tip -> error "Map.deleteAt: index out of range" @@ -1703,7 +1725,11 @@ lookupMin (Bin _ k x l _) = Just $! kvToTuple (lookupMinSure k x l) -- > findMin (fromList [(5,"a"), (3,"b")]) == (3,"b") -- > findMin empty Error: empty map has no minimal element +#if __GLASGOW_HASKELL__ >= 800 findMin :: HasCallStack => Map k a -> (k,a) +#else +findMin :: Map k a -> (k,a) +#endif findMin t | Just r <- lookupMin t = r | otherwise = error "Map.findMin: empty map has no minimal element" @@ -1731,7 +1757,11 @@ lookupMax (Bin _ k x _ r) = Just $! kvToTuple (lookupMaxSure k x r) -- > findMax (fromList [(5,"a"), (3,"b")]) == (5,"a") -- > findMax empty Error: empty map has no maximal element +#if __GLASGOW_HASKELL__ >= 800 findMax :: HasCallStack => Map k a -> (k,a) +#else +findMax :: Map k a -> (k,a) +#endif findMax t | Just r <- lookupMax t = r | otherwise = error "Map.findMax: empty map has no maximal element" @@ -2849,7 +2879,11 @@ mergeA -- @only2@ are 'id' and @'const' 'empty'@, but for example @'map' f@, -- @'filterWithKey' f@, or @'mapMaybeWithKey' f@ could be used for any @f@. +#if __GLASGOW_HASKELL__ >= 800 mergeWithKey :: (HasCallStack, Ord k) +#else +mergeWithKey :: Ord k +#endif => (k -> a -> b -> Maybe c) -> (Map k a -> Map k c) -> (Map k b -> Map k c) @@ -4183,7 +4217,11 @@ maxViewSure !k x !l r = case r of -- Calls 'error' if the map is empty. -- -- __Note__: This function is partial. Prefer 'minViewWithKey'. +#if __GLASGOW_HASKELL__ >= 800 deleteFindMin :: HasCallStack => Map k a -> ((k,a),Map k a) +#else +deleteFindMin :: Map k a -> ((k,a),Map k a) +#endif deleteFindMin t = case minViewWithKey t of Nothing -> (error "Map.deleteFindMin: can not return the minimal element of an empty map", Tip) Just res -> res @@ -4193,7 +4231,11 @@ deleteFindMin t = case minViewWithKey t of -- Calls 'error' if the map is empty. -- -- __Note__: This function is partial. Prefer 'maxViewWithKey'. +#if __GLASGOW_HASKELL__ >= 800 deleteFindMax :: HasCallStack => Map k a -> ((k,a),Map k a) +#else +deleteFindMax :: Map k a -> ((k,a),Map k a) +#endif deleteFindMax t = case maxViewWithKey t of Nothing -> (error "Map.deleteFindMax: can not return the maximal element of an empty map", Tip) Just res -> res diff --git a/containers/src/Data/Map/Strict/Internal.hs b/containers/src/Data/Map/Strict/Internal.hs index 2b89250df..b4a6ba9b3 100644 --- a/containers/src/Data/Map/Strict/Internal.hs +++ b/containers/src/Data/Map/Strict/Internal.hs @@ -424,7 +424,9 @@ import Data.Coerce import Data.Functor.Identity (Identity (..)) #endif +#if __GLASGOW_HASKELL__ >= 800 import GHC.Stack (HasCallStack) +#endif import qualified Data.Foldable as Foldable @@ -871,7 +873,11 @@ atKeyIdentity k f t = Identity $ atKeyPlain Strict k (coerce f) t -- > updateAt (\_ _ -> Nothing) 2 (fromList [(5,"a"), (3,"b")]) Error: index out of range -- > updateAt (\_ _ -> Nothing) (-1) (fromList [(5,"a"), (3,"b")]) Error: index out of range +#if __GLASGOW_HASKELL__ >= 800 updateAt :: HasCallStack => (k -> a -> Maybe a) -> Int -> Map k a -> Map k a +#else +updateAt :: (k -> a -> Maybe a) -> Int -> Map k a -> Map k a +#endif updateAt f i t = i `seq` case t of Tip -> error "Map.updateAt: index out of range" diff --git a/containers/src/Data/Sequence/Internal.hs b/containers/src/Data/Sequence/Internal.hs index 1dd34d5ac..92d5483a5 100644 --- a/containers/src/Data/Sequence/Internal.hs +++ b/containers/src/Data/Sequence/Internal.hs @@ -235,7 +235,9 @@ import Utils.Containers.Internal.StrictPair (StrictPair (..), toPair) import Control.Monad.Zip (MonadZip (..)) import Control.Monad.Fix (MonadFix (..), fix) +#if __GLASGOW_HASKELL__ >= 800 import GHC.Stack (HasCallStack) +#endif default () @@ -520,7 +522,11 @@ instance MonadFix Seq where -- This is just like the instance for lists, but we can take advantage of -- constant-time length and logarithmic-time indexing to speed things up. -- Using fromFunction, we make this about as lazy as we can. +#if __GLASGOW_HASKELL__ >= 800 mfixSeq :: HasCallStack => (a -> Seq a) -> Seq a +#else +mfixSeq :: (a -> Seq a) -> Seq a +#endif mfixSeq f = fromFunction (length (f err)) (\k -> fix (\xk -> f xk `index` k)) where err = error "mfix for Data.Sequence.Seq applied to strict function" @@ -1766,7 +1772,11 @@ singleton x = Seq (Single (Elem x)) -- Calls 'error' if @n < 0@. -- -- __Note__: This function is partial. +#if __GLASGOW_HASKELL__ >= 800 replicate :: HasCallStack => Int -> a -> Seq a +#else +replicate :: Int -> a -> Seq a +#endif replicate n x | n >= 0 = runIdentity (replicateA n (Identity x)) | otherwise = error "replicate takes a nonnegative integer argument" @@ -1779,7 +1789,11 @@ replicate n x -- __Note__: This function is partial. -- -- > replicateA n x = sequenceA (replicate n x) +#if __GLASGOW_HASKELL__ >= 800 replicateA :: (HasCallStack, Applicative f) => Int -> f a -> f (Seq a) +#else +replicateA :: Applicative f => Int -> f a -> f (Seq a) +#endif replicateA n x | n >= 0 = Seq <$> applicativeTree n 1 (Elem <$> x) | otherwise = error "replicateA takes a nonnegative integer argument" @@ -1788,7 +1802,11 @@ replicateA n x -- | Synonym for 'replicateA'. -- -- This definition exists for backwards compatibility. +#if __GLASGOW_HASKELL__ >= 800 replicateM :: (HasCallStack, Applicative m) => Int -> m a -> m (Seq a) +#else +replicateM :: (Applicative m) => Int -> m a -> m (Seq a) +#endif replicateM = replicateA -- | \(O(\log k)\). @'cycleTaking' k xs@ forms a sequence of length @k@ by @@ -1806,7 +1824,11 @@ replicateM = replicateA -- __Note__: This function is partial. -- -- @since 0.5.8 +#if __GLASGOW_HASKELL__ >= 800 cycleTaking :: HasCallStack => Int -> Seq a -> Seq a +#else +cycleTaking :: Int -> Seq a -> Seq a +#endif cycleTaking n !_xs | n <= 0 = empty cycleTaking _n xs | null xs = error "cycleTaking cannot take a positive number of elements from an empty cycle." cycleTaking n xs = cycleNTimes reps xs >< take final xs @@ -2220,7 +2242,11 @@ unfoldl f = unfoldl' empty -- Calls 'error' if @n < 0@. -- -- __Note__: This function is partial. +#if __GLASGOW_HASKELL__ >= 800 iterateN :: HasCallStack => Int -> (a -> a) -> a -> Seq a +#else +iterateN :: Int -> (a -> a) -> a -> Seq a +#endif iterateN n f x | n >= 0 = replicateA n (State (\ y -> (f y, y))) `execState` x | otherwise = error "iterateN takes a nonnegative integer argument" @@ -2403,7 +2429,11 @@ scanl f z0 xs = z0 <| snd (mapAccumL (\ x z -> let x' = f x z in (x', x')) z0 xs -- __Note__: This function is partial. -- -- > scanl1 f (fromList [x1, x2, ...]) = fromList [x1, x1 `f` x2, ...] +#if __GLASGOW_HASKELL__ >= 800 scanl1 :: HasCallStack => (a -> a -> a) -> Seq a -> Seq a +#else +scanl1 :: (a -> a -> a) -> Seq a -> Seq a +#endif scanl1 f xs = case viewl xs of EmptyL -> error "scanl1 takes a nonempty sequence as an argument" x :< xs' -> scanl f x xs' @@ -2417,7 +2447,11 @@ scanr f z0 xs = snd (mapAccumR (\ z x -> let z' = f x z in (z', z')) z0 xs) |> z -- Calls 'error' if the sequence is empty. -- -- __Note__: This function is partial. +#if __GLASGOW_HASKELL__ >= 800 scanr1 :: HasCallStack => (a -> a -> a) -> Seq a -> Seq a +#else +scanr1 :: (a -> a -> a) -> Seq a -> Seq a +#endif scanr1 f xs = case viewr xs of EmptyR -> error "scanr1 takes a nonempty sequence as an argument" xs' :> x -> scanr f x xs' @@ -2437,7 +2471,11 @@ scanr1 f xs = case viewr xs of -- element until the result is forced. It can therefore lead to a space -- leak if the result is stored, unforced, in another structure. To retrieve -- an element immediately without forcing it, use 'lookup' or '(!?)'. +#if __GLASGOW_HASKELL__ >= 800 index :: HasCallStack => Seq a -> Int -> a +#else +index :: Seq a -> Int -> a +#endif index (Seq xs) i -- See note on unsigned arithmetic in splitAt | fromIntegral i < (fromIntegral (size xs) :: Word) = case lookupTree i xs of @@ -3409,7 +3447,11 @@ valid. -- __Note__: This function is partial. -- -- @since 0.5.6.2 +#if __GLASGOW_HASKELL__ >= 800 fromFunction :: HasCallStack => Int -> (Int -> a) -> Seq a +#else +fromFunction :: Int -> (Int -> a) -> Seq a +#endif fromFunction len f | len < 0 = error "Data.Sequence.fromFunction called with negative len" | len == 0 = empty | otherwise = Seq $ create (lift_elem f) 1 0 len @@ -3991,7 +4033,11 @@ splitSuffixN i s pr m (Four a b c d) -- __Note__: This function is partial. -- -- @since 0.5.8 +#if __GLASGOW_HASKELL__ >= 800 chunksOf :: HasCallStack => Int -> Seq a -> Seq (Seq a) +#else +chunksOf :: Int -> Seq a -> Seq (Seq a) +#endif chunksOf n xs | n <= 0 = if null xs then empty @@ -4988,7 +5034,11 @@ zipWith f s1 s2 = zipWith' f s1' s2' s2' = take minLen s2 -- | A version of zipWith that assumes the sequences have the same length. +#if __GLASGOW_HASKELL__ >= 800 zipWith' :: HasCallStack => (a -> b -> c) -> Seq a -> Seq b -> Seq c +#else +zipWith' :: (a -> b -> c) -> Seq a -> Seq b -> Seq c +#endif zipWith' f s1 s2 = splitMap uncheckedSplitAt goLeaf s2 s1 where goLeaf (Seq (Single (Elem b))) a = f a b @@ -5033,7 +5083,11 @@ zipWith4 f s1 s2 s3 s4 = zipWith' ($) (zipWith3' f s1' s2' s3') s4' -- | fromList2, given a list and its length, constructs a completely -- balanced Seq whose elements are that list using the replicateA -- generalization. +#if __GLASGOW_HASKELL__ >= 800 fromList2 :: HasCallStack => Int -> [a] -> Seq a +#else +fromList2 :: Int -> [a] -> Seq a +#endif fromList2 n = execState (replicateA n (State ht)) where ht (x:xs) = (xs, x) diff --git a/containers/src/Data/Set/Internal.hs b/containers/src/Data/Set/Internal.hs index 82668ff21..a9379fa6f 100644 --- a/containers/src/Data/Set/Internal.hs +++ b/containers/src/Data/Set/Internal.hs @@ -258,7 +258,9 @@ import Language.Haskell.TH () import Data.Coerce (coerce) #endif +#if __GLASGOW_HASKELL__ >= 800 import GHC.Stack (HasCallStack) +#endif {-------------------------------------------------------------------- @@ -780,7 +782,11 @@ lookupMin (Bin _ x l _) = Just $! lookupMinSure x l -- empty. -- -- __Note__: This function is partial. Prefer 'lookupMin'. +#if MIN_VERSION_base(4,9,0) findMin :: HasCallStack => Set a -> a +#else +findMin :: Set a -> a +#endif findMin t | Just r <- lookupMin t = r | otherwise = error "Set.findMin: empty set has no minimal element" @@ -803,7 +809,11 @@ lookupMax (Bin _ x _ r) = Just $! lookupMaxSure x r -- empty. -- -- __Note__: This function is partial. Prefer 'lookupMax'. +#if __GLASGOW_HASKELL__ >= 800 findMax :: HasCallStack => Set a -> a +#else +findMax :: Set a -> a +#endif findMax t | Just r <- lookupMax t = r | otherwise = error "Set.findMax: empty set has no maximal element" @@ -1459,7 +1469,11 @@ splitMember x (Bin _ y l r) -- @since 0.5.4 -- See Note: Type of local 'go' function +#if __GLASGOW_HASKELL__ >= 800 findIndex :: (HasCallStack, Ord a) => a -> Set a -> Int +#else +findIndex :: Ord a => a -> Set a -> Int +#endif findIndex = go 0 where go :: Ord a => Int -> a -> Set a -> Int @@ -1509,7 +1523,11 @@ lookupIndex = go 0 -- -- @since 0.5.4 +#if __GLASGOW_HASKELL__ >= 800 elemAt :: HasCallStack => Int -> Set a -> a +#else +elemAt :: Int -> Set a -> a +#endif elemAt !_ Tip = error "Set.elemAt: index out of range" elemAt i (Bin _ x l r) = case compare i sizeL of @@ -1532,7 +1550,11 @@ elemAt i (Bin _ x l r) -- -- @since 0.5.4 +#if __GLASGOW_HASKELL__ >= 800 deleteAt :: HasCallStack => Int -> Set a -> Set a +#else +deleteAt :: Int -> Set a -> Set a +#endif deleteAt !i t = case t of Tip -> error "Set.deleteAt: index out of range" @@ -1830,7 +1852,11 @@ glue l@(Bin sl xl ll lr) r@(Bin sr xr rl rr) -- Calls 'error' if the set is empty. -- -- __Note__: This function is partial. Prefer 'minView'. +#if __GLASGOW_HASKELL__ >= 800 deleteFindMin :: HasCallStack => Set a -> (a,Set a) +#else +deleteFindMin :: Set a -> (a,Set a) +#endif deleteFindMin t | Just r <- minView t = r | otherwise = (error "Set.deleteFindMin: can not return the minimal element of an empty set", Tip) @@ -1840,7 +1866,11 @@ deleteFindMin t -- Calls 'error' if the set is empty. -- -- __Note__: This function is partial. Prefer 'maxView'. +#if __GLASGOW_HASKELL__ >= 800 deleteFindMax :: HasCallStack => Set a -> (a,Set a) +#else +deleteFindMax :: Set a -> (a,Set a) +#endif deleteFindMax t | Just r <- maxView t = r | otherwise = (error "Set.deleteFindMax: can not return the maximal element of an empty set", Tip) From ea327ec87366efe0038f61b7d48d06ef816ec6f2 Mon Sep 17 00:00:00 2001 From: "Daniel.Winograd-Cort" Date: Mon, 15 Jan 2018 12:42:45 -0500 Subject: [PATCH 3/8] Remove HasCallStack where undesired --- containers/src/Data/Map/Internal.hs | 4 ---- containers/src/Data/Sequence/Internal.hs | 4 ---- 2 files changed, 8 deletions(-) diff --git a/containers/src/Data/Map/Internal.hs b/containers/src/Data/Map/Internal.hs index 873b9b088..ac1b66283 100644 --- a/containers/src/Data/Map/Internal.hs +++ b/containers/src/Data/Map/Internal.hs @@ -2879,11 +2879,7 @@ mergeA -- @only2@ are 'id' and @'const' 'empty'@, but for example @'map' f@, -- @'filterWithKey' f@, or @'mapMaybeWithKey' f@ could be used for any @f@. -#if __GLASGOW_HASKELL__ >= 800 -mergeWithKey :: (HasCallStack, Ord k) -#else mergeWithKey :: Ord k -#endif => (k -> a -> b -> Maybe c) -> (Map k a -> Map k c) -> (Map k b -> Map k c) diff --git a/containers/src/Data/Sequence/Internal.hs b/containers/src/Data/Sequence/Internal.hs index 92d5483a5..62db79dec 100644 --- a/containers/src/Data/Sequence/Internal.hs +++ b/containers/src/Data/Sequence/Internal.hs @@ -5034,11 +5034,7 @@ zipWith f s1 s2 = zipWith' f s1' s2' s2' = take minLen s2 -- | A version of zipWith that assumes the sequences have the same length. -#if __GLASGOW_HASKELL__ >= 800 -zipWith' :: HasCallStack => (a -> b -> c) -> Seq a -> Seq b -> Seq c -#else zipWith' :: (a -> b -> c) -> Seq a -> Seq b -> Seq c -#endif zipWith' f s1 s2 = splitMap uncheckedSplitAt goLeaf s2 s1 where goLeaf (Seq (Single (Elem b))) a = f a b From 963ec90836915517daf7574c733daab81461f2c2 Mon Sep 17 00:00:00 2001 From: "Daniel.Winograd-Cort" Date: Mon, 15 Jan 2018 17:07:58 -0500 Subject: [PATCH 4/8] Fixes --- containers/src/Data/IntMap/Internal.hs | 16 ++----- containers/src/Data/Map/Internal.hs | 55 +++++++++++++++------- containers/src/Data/Map/Strict/Internal.hs | 14 +++++- containers/src/Data/Sequence/Internal.hs | 4 -- containers/src/Data/Set/Internal.hs | 23 ++++++++- 5 files changed, 74 insertions(+), 38 deletions(-) diff --git a/containers/src/Data/IntMap/Internal.hs b/containers/src/Data/IntMap/Internal.hs index 836408ad7..d93e261f7 100644 --- a/containers/src/Data/IntMap/Internal.hs +++ b/containers/src/Data/IntMap/Internal.hs @@ -437,7 +437,9 @@ deriving instance Lift a => Lift (IntMap a) #else (!) :: IntMap a -> Key -> a #endif -(!) m k = find k m +(!) m k + | Just a <- lookup k m = a + | otherwise = error ("IntMap.!: key " ++ show k ++ " is not an element of the map") -- | \(O(\min(n,W))\). Find the value at a key. -- Returns 'Nothing' when the element can not be found. @@ -655,18 +657,6 @@ lookup !k = go | otherwise = Nothing go Nil = Nothing --- See Note: Local 'go' functions and capturing] -find :: HasCallStack => Key -> IntMap a -> a -find !k = go - where - go (Bin p l r) | left k p = go l - | otherwise = go r - go (Tip kx x) | k == kx = x - | otherwise = not_found - go Nil = not_found - - not_found = error ("IntMap.!: key " ++ show k ++ " is not an element of the map") - -- | \(O(\min(n,W))\). The expression @('findWithDefault' def k map)@ -- returns the value at key @k@ or returns @def@ when the key is not an -- element of the map. diff --git a/containers/src/Data/Map/Internal.hs b/containers/src/Data/Map/Internal.hs index ac1b66283..c5462fb20 100644 --- a/containers/src/Data/Map/Internal.hs +++ b/containers/src/Data/Map/Internal.hs @@ -448,7 +448,9 @@ infixl 9 !,!?,\\ -- #else (!) :: Ord k => Map k a -> k -> a #endif -(!) m k = find k m +(!) m k + | Just a <- lookup k m = a + | otherwise = error "Map.!: given key is not an element in the map" #if __GLASGOW_HASKELL__ {-# INLINE (!) #-} #endif @@ -633,20 +635,6 @@ notMember k m = not $ member k m {-# INLINE notMember #-} #endif -find :: Ord k => k -> Map k a -> a -find = go - where - go !_ Tip = error "Map.!: given key is not an element in the map" - go k (Bin _ kx x l r) = case compare k kx of - LT -> go k l - GT -> go k r - EQ -> x -#if __GLASGOW_HASKELL__ -{-# INLINABLE find #-} -#else -{-# INLINE find #-} -#endif - -- | \(O(\log n)\). The expression @('findWithDefault' def k map)@ returns -- the value at key @k@ or returns default value @def@ -- when the key is not in the map. @@ -1543,9 +1531,17 @@ lookupIndex = go 0 #if __GLASGOW_HASKELL__ >= 800 elemAt :: HasCallStack => Int -> Map k a -> (k,a) +elemAt = go where + go !_ Tip = error "Map.elemAt: index out of range" + go i (Bin _ kx x l r) + = case compare i sizeL of + LT -> elemAt i l + GT -> elemAt (i-sizeL-1) r + EQ -> (kx,x) + where + sizeL = size l #else elemAt :: Int -> Map k a -> (k,a) -#endif elemAt !_ Tip = error "Map.elemAt: index out of range" elemAt i (Bin _ kx x l r) = case compare i sizeL of @@ -1554,6 +1550,7 @@ elemAt i (Bin _ kx x l r) EQ -> (kx,x) where sizeL = size l +#endif -- | \(O(\log n)\). Take a given number of entries in key order, beginning -- with the smallest keys. @@ -1638,9 +1635,20 @@ splitAt i0 m0 #if __GLASGOW_HASKELL__ >= 800 updateAt :: HasCallStack => (k -> a -> Maybe a) -> Int -> Map k a -> Map k a +updateAt = go where + go f !i t = + case t of + Tip -> error "Map.updateAt: index out of range" + Bin sx kx x l r -> case compare i sizeL of + LT -> balanceR kx x (go f i l) r + GT -> balanceL kx x l (go f (i-sizeL-1) r) + EQ -> case f kx x of + Just x' -> Bin sx kx x' l r + Nothing -> glue l r + where + sizeL = size l #else updateAt :: (k -> a -> Maybe a) -> Int -> Map k a -> Map k a -#endif updateAt f !i t = case t of Tip -> error "Map.updateAt: index out of range" @@ -1652,6 +1660,7 @@ updateAt f !i t = Nothing -> glue l r where sizeL = size l +#endif -- | \(O(\log n)\). Delete the element at /index/, i.e. by its zero-based index in -- the sequence sorted by keys. If the /index/ is out of range (less than zero, @@ -1666,9 +1675,18 @@ updateAt f !i t = #if __GLASGOW_HASKELL__ >= 800 deleteAt :: HasCallStack => Int -> Map k a -> Map k a +deleteAt = go where + go !i t = + case t of + Tip -> error "Map.deleteAt: index out of range" + Bin _ kx x l r -> case compare i sizeL of + LT -> balanceR kx x (go i l) r + GT -> balanceL kx x l (go (i-sizeL-1) r) + EQ -> glue l r + where + sizeL = size l #else deleteAt :: Int -> Map k a -> Map k a -#endif deleteAt !i t = case t of Tip -> error "Map.deleteAt: index out of range" @@ -1678,6 +1696,7 @@ deleteAt !i t = EQ -> glue l r where sizeL = size l +#endif {-------------------------------------------------------------------- diff --git a/containers/src/Data/Map/Strict/Internal.hs b/containers/src/Data/Map/Strict/Internal.hs index b4a6ba9b3..e066a2904 100644 --- a/containers/src/Data/Map/Strict/Internal.hs +++ b/containers/src/Data/Map/Strict/Internal.hs @@ -875,9 +875,20 @@ atKeyIdentity k f t = Identity $ atKeyPlain Strict k (coerce f) t #if __GLASGOW_HASKELL__ >= 800 updateAt :: HasCallStack => (k -> a -> Maybe a) -> Int -> Map k a -> Map k a +updateAt = go where + go f i t = i `seq` + case t of + Tip -> error "Map.updateAt: index out of range" + Bin sx kx x l r -> case compare i sizeL of + LT -> balanceR kx x (go f i l) r + GT -> balanceL kx x l (go f (i-sizeL-1) r) + EQ -> case f kx x of + Just x' -> x' `seq` Bin sx kx x' l r + Nothing -> glue l r + where + sizeL = size l #else updateAt :: (k -> a -> Maybe a) -> Int -> Map k a -> Map k a -#endif updateAt f i t = i `seq` case t of Tip -> error "Map.updateAt: index out of range" @@ -889,6 +900,7 @@ updateAt f i t = i `seq` Nothing -> glue l r where sizeL = size l +#endif {-------------------------------------------------------------------- Minimal, Maximal diff --git a/containers/src/Data/Sequence/Internal.hs b/containers/src/Data/Sequence/Internal.hs index 62db79dec..11061864e 100644 --- a/containers/src/Data/Sequence/Internal.hs +++ b/containers/src/Data/Sequence/Internal.hs @@ -5079,11 +5079,7 @@ zipWith4 f s1 s2 s3 s4 = zipWith' ($) (zipWith3' f s1' s2' s3') s4' -- | fromList2, given a list and its length, constructs a completely -- balanced Seq whose elements are that list using the replicateA -- generalization. -#if __GLASGOW_HASKELL__ >= 800 -fromList2 :: HasCallStack => Int -> [a] -> Seq a -#else fromList2 :: Int -> [a] -> Seq a -#endif fromList2 n = execState (replicateA n (State ht)) where ht (x:xs) = (xs, x) diff --git a/containers/src/Data/Set/Internal.hs b/containers/src/Data/Set/Internal.hs index a9379fa6f..ca1d7e2b3 100644 --- a/containers/src/Data/Set/Internal.hs +++ b/containers/src/Data/Set/Internal.hs @@ -1525,9 +1525,17 @@ lookupIndex = go 0 #if __GLASGOW_HASKELL__ >= 800 elemAt :: HasCallStack => Int -> Set a -> a +elemAt = go where + go !_ Tip = error "Set.elemAt: index out of range" + go i (Bin _ x l r) + = case compare i sizeL of + LT -> go i l + GT -> go (i-sizeL-1) r + EQ -> x + where + sizeL = size l #else elemAt :: Int -> Set a -> a -#endif elemAt !_ Tip = error "Set.elemAt: index out of range" elemAt i (Bin _ x l r) = case compare i sizeL of @@ -1536,6 +1544,7 @@ elemAt i (Bin _ x l r) EQ -> x where sizeL = size l +#endif -- | \(O(\log n)\). Delete the element at /index/, i.e. by its zero-based index in -- the sorted sequence of elements. If the /index/ is out of range (less than zero, @@ -1552,9 +1561,18 @@ elemAt i (Bin _ x l r) #if __GLASGOW_HASKELL__ >= 800 deleteAt :: HasCallStack => Int -> Set a -> Set a +deleteAt = go where + go !i t = + case t of + Tip -> error "Set.deleteAt: index out of range" + Bin _ x l r -> case compare i sizeL of + LT -> balanceR x (go i l) r + GT -> balanceL x l (go (i-sizeL-1) r) + EQ -> glue l r + where + sizeL = size l #else deleteAt :: Int -> Set a -> Set a -#endif deleteAt !i t = case t of Tip -> error "Set.deleteAt: index out of range" @@ -1564,6 +1582,7 @@ deleteAt !i t = EQ -> glue l r where sizeL = size l +#endif -- | \(O(\log n)\). Take a given number of elements in order, beginning -- with the smallest ones. From ff1be0aca44058d8e94a75d6fee1b929f966823f Mon Sep 17 00:00:00 2001 From: "Daniel.Winograd-Cort" Date: Tue, 6 Feb 2018 12:15:28 -0500 Subject: [PATCH 5/8] Reverting behavior of (!) to not allocate Just --- containers/src/Data/IntMap/Internal.hs | 12 +++++++++--- containers/src/Data/Map/Internal.hs | 10 +++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/containers/src/Data/IntMap/Internal.hs b/containers/src/Data/IntMap/Internal.hs index d93e261f7..eb7fc1e57 100644 --- a/containers/src/Data/IntMap/Internal.hs +++ b/containers/src/Data/IntMap/Internal.hs @@ -437,9 +437,15 @@ deriving instance Lift a => Lift (IntMap a) #else (!) :: IntMap a -> Key -> a #endif -(!) m k - | Just a <- lookup k m = a - | otherwise = error ("IntMap.!: key " ++ show k ++ " is not an element of the map") +(!) m0 !k = go m0 + where + go (Bin p m l r) | nomatch k p m = not_found + | zero k m = go l + | otherwise = go r + go (Tip kx x) | k == kx = x + | otherwise = not_found + go Nil = not_found + not_found = error ("IntMap.!: key " ++ show k ++ " is not an element of the map") -- | \(O(\min(n,W))\). Find the value at a key. -- Returns 'Nothing' when the element can not be found. diff --git a/containers/src/Data/Map/Internal.hs b/containers/src/Data/Map/Internal.hs index c5462fb20..91a44d8e9 100644 --- a/containers/src/Data/Map/Internal.hs +++ b/containers/src/Data/Map/Internal.hs @@ -448,9 +448,13 @@ infixl 9 !,!?,\\ -- #else (!) :: Ord k => Map k a -> k -> a #endif -(!) m k - | Just a <- lookup k m = a - | otherwise = error "Map.!: given key is not an element in the map" +(!) m !k = go m + where + go Tip = error "Map.!: given key is not an element in the map" + go (Bin _ kx x l r) = case compare k kx of + LT -> go l + GT -> go r + EQ -> x #if __GLASGOW_HASKELL__ {-# INLINE (!) #-} #endif From f57b117f98906b72dbb809e1afedcbcfa674319f Mon Sep 17 00:00:00 2001 From: L0neGamer Date: Wed, 10 Sep 2025 20:22:29 +0100 Subject: [PATCH 6/8] fixing revertion --- containers/src/Data/IntMap/Internal.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/containers/src/Data/IntMap/Internal.hs b/containers/src/Data/IntMap/Internal.hs index eb7fc1e57..e1599fb3a 100644 --- a/containers/src/Data/IntMap/Internal.hs +++ b/containers/src/Data/IntMap/Internal.hs @@ -439,12 +439,12 @@ deriving instance Lift a => Lift (IntMap a) #endif (!) m0 !k = go m0 where - go (Bin p m l r) | nomatch k p m = not_found - | zero k m = go l - | otherwise = go r + go (Bin p l r) | left k p = go l + | otherwise = go r go (Tip kx x) | k == kx = x | otherwise = not_found go Nil = not_found + not_found = error ("IntMap.!: key " ++ show k ++ " is not an element of the map") -- | \(O(\min(n,W))\). Find the value at a key. From 0d4a055afe076aae33b5e0a1ed89988ff7697ccf Mon Sep 17 00:00:00 2001 From: L0neGamer Date: Thu, 11 Sep 2025 21:10:24 +0100 Subject: [PATCH 7/8] remove hascallstack from internal functions --- containers/src/Data/IntMap/Internal.hs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/containers/src/Data/IntMap/Internal.hs b/containers/src/Data/IntMap/Internal.hs index e1599fb3a..d0d345e48 100644 --- a/containers/src/Data/IntMap/Internal.hs +++ b/containers/src/Data/IntMap/Internal.hs @@ -2389,11 +2389,7 @@ kvToTuple :: KeyValue a -> (Key, a) kvToTuple (KeyValue k x) = (k, x) {-# INLINE kvToTuple #-} -#if __GLASGOW_HASKELL__ >= 800 -lookupMinSure :: HasCallStack => IntMap a -> KeyValue a -#else lookupMinSure :: IntMap a -> KeyValue a -#endif lookupMinSure (Tip k v) = KeyValue k v lookupMinSure (Bin _ l _) = lookupMinSure l lookupMinSure Nil = error "lookupMinSure Nil" @@ -2418,11 +2414,7 @@ findMin t | Just r <- lookupMin t = r | otherwise = error "findMin: empty map has no minimal element" -#if __GLASGOW_HASKELL__ >= 800 -lookupMaxSure :: HasCallStack => IntMap a -> KeyValue a -#else lookupMaxSure :: IntMap a -> KeyValue a -#endif lookupMaxSure (Tip k v) = KeyValue k v lookupMaxSure (Bin _ _ r) = lookupMaxSure r lookupMaxSure Nil = error "lookupMaxSure Nil" From 01f9bcc48844807bd7ea2344136ab2a1cb00fa05 Mon Sep 17 00:00:00 2001 From: L0neGamer Date: Thu, 11 Sep 2025 22:16:11 +0100 Subject: [PATCH 8/8] use glasgow haskell for hascallstack constraint --- containers/src/Data/Set/Internal.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/containers/src/Data/Set/Internal.hs b/containers/src/Data/Set/Internal.hs index ca1d7e2b3..08b6fa90a 100644 --- a/containers/src/Data/Set/Internal.hs +++ b/containers/src/Data/Set/Internal.hs @@ -782,7 +782,7 @@ lookupMin (Bin _ x l _) = Just $! lookupMinSure x l -- empty. -- -- __Note__: This function is partial. Prefer 'lookupMin'. -#if MIN_VERSION_base(4,9,0) +#if __GLASGOW_HASKELL__ >= 800 findMin :: HasCallStack => Set a -> a #else findMin :: Set a -> a