safe 0.3.17 → 0.3.21
raw patch · 7 files changed
Files
- CHANGES.txt +11/−0
- LICENSE +1/−1
- README.md +1/−1
- Safe.hs +92/−21
- Safe/Exact.hs +6/−5
- Safe/Foldable.hs +65/−31
- safe.cabal +5/−5
CHANGES.txt view
@@ -1,5 +1,16 @@ Changelog for Safe +0.3.21, released 2024-01-18+ #34, mark headErr/tailErr as Partial+0.3.20, released 2024-01-14+ #34, add headErr, tailErr+ #33, avoid using head/tail to avoid x-partial+0.3.19, released 2020-05-24+ #30, undeprecate maximumDef and friends, fold*1Def+0.3.18, released 2019-12-04+ #27, deprecate maximumDef and friends, fold*1Def+ #27, add maximumBounded and friends+ Stop supporting GHC 7.4 to 7.8 0.3.17, released 2018-03-09 Improve the display of errors, less internal callstack Add a few missing Partial constraints
LICENSE view
@@ -1,4 +1,4 @@-Copyright Neil Mitchell 2007-2018.+Copyright Neil Mitchell 2007-2024. All rights reserved. Redistribution and use in source and binary forms, with or without
README.md view
@@ -1,4 +1,4 @@-# Safe [](https://hackage.haskell.org/package/safe) [](https://travis-ci.org/ndmitchell/safe)+# Safe [](https://hackage.haskell.org/package/safe) [](https://www.stackage.org/package/safe) [](https://github.com/ndmitchell/safe/actions) A library wrapping `Prelude`/`Data.List` functions that can throw exceptions, such as `head` and `!!`. Each unsafe function has up to four variants, e.g. with `tail`:
Safe.hs view
@@ -1,11 +1,16 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ConstraintKinds #-}++{-# OPTIONS_GHC -Wno-x-partial -Wno-unrecognised-warning-flags #-}+ {- | A module wrapping @Prelude@/@Data.List@ functions that can throw exceptions, such as @head@ and @!!@.-Each unsafe function has up to four variants, e.g. with @tail@:+Each unsafe function has up to five variants, e.g. with @tail@: -* @'tail' :: [a] -> [a]@, raises an error on @tail []@.+* @'tail' :: [a] -> [a]@, raises an error on @tail []@, as provided by 'Prelude'. +* @'tailErr' :: [a] -> [a]@, alias for @tail@ that doesn't trigger an @x-partial@ warning and does raise errors.+ * @'tailMay' :: [a] -> /Maybe/ [a]@, turns errors into @Nothing@. * @'tailDef' :: /[a]/ -> [a] -> [a]@, takes a default to return on errors.@@ -23,15 +28,20 @@ module Safe( -- * New functions abort, at, lookupJust, findJust, elemIndexJust, findIndexJust,+ -- * Partial functions+ tailErr, headErr, -- * Safe wrappers tailMay, tailDef, tailNote, tailSafe, initMay, initDef, initNote, initSafe, headMay, headDef, headNote, lastMay, lastDef, lastNote,- minimumMay, minimumDef, minimumNote,- maximumMay, maximumDef, maximumNote,- minimumByMay, minimumByDef, minimumByNote,- maximumByMay, maximumByDef, maximumByNote,+ minimumMay, minimumNote,+ maximumMay, maximumNote,+ minimumByMay, minimumByNote,+ maximumByMay, maximumByNote,+ minimumBoundBy, maximumBoundBy,+ maximumBounded, maximumBound,+ minimumBounded, minimumBound, foldr1May, foldr1Def, foldr1Note, foldl1May, foldl1Def, foldl1Note, foldl1May', foldl1Def', foldl1Note',@@ -50,6 +60,8 @@ succMay, succDef, succNote, succSafe, predMay, predDef, predNote, predSafe, indexMay, indexDef, indexNote,+ -- * Discouraged+ minimumDef, maximumDef, minimumByDef, maximumByDef ) where import Safe.Util@@ -89,11 +101,28 @@ --------------------------------------------------------------------- -- WRAPPERS +-- | Identical to 'tail', namely that fails on an empty list.+-- Useful to avoid the @x-partial@ warning introduced in GHC 9.8.+--+-- > tailErr [] = error "Prelude.tail: empty list"+-- > tailErr [1,2,3] = [2,3]+tailErr :: Partial => [a] -> [a]+tailErr = tail++-- | Identical to 'head', namely that fails on an empty list.+-- Useful to avoid the @x-partial@ warning introduced in GHC 9.8.+--+-- > headErr [] = error "Prelude.head: empty list"+-- > headErr [1,2,3] = 1+headErr :: Partial => [a] -> a+headErr = head+ -- | -- > tailMay [] = Nothing -- > tailMay [1,3,4] = Just [3,4] tailMay :: [a] -> Maybe [a]-tailMay = liftMay null tail+tailMay [] = Nothing+tailMay (_:xs) = Just xs -- | -- > tailDef [12] [] = [12]@@ -129,7 +158,7 @@ headMay, lastMay :: [a] -> Maybe a-headMay = liftMay null head+headMay = listToMaybe lastMay = liftMay null last headDef, lastDef :: a -> [a] -> a@@ -144,10 +173,6 @@ minimumMay = liftMay null minimum maximumMay = liftMay null maximum -minimumDef, maximumDef :: Ord a => a -> [a] -> a-minimumDef def = fromMaybe def . minimumMay-maximumDef def = fromMaybe def . maximumMay- minimumNote, maximumNote :: (Partial, Ord a) => String -> [a] -> a minimumNote note x = withFrozenCallStack $ fromNote note "minumumNote []" $ minimumMay x maximumNote note x = withFrozenCallStack $ fromNote note "maximumNote []" $ maximumMay x@@ -156,25 +181,45 @@ minimumByMay = liftMay null . minimumBy maximumByMay = liftMay null . maximumBy -minimumByDef, maximumByDef :: a -> (a -> a -> Ordering) -> [a] -> a-minimumByDef def = fromMaybe def .^ minimumByMay-maximumByDef def = fromMaybe def .^ maximumByMay- minimumByNote, maximumByNote :: Partial => String -> (a -> a -> Ordering) -> [a] -> a minimumByNote note f x = withFrozenCallStack $ fromNote note "minumumByNote []" $ minimumByMay f x maximumByNote note f x = withFrozenCallStack $ fromNote note "maximumByNote []" $ maximumByMay f x +-- | The largest element of a list with respect to the+-- given comparison function. The result is bounded by the value given as the first argument.+maximumBoundBy :: a -> (a -> a -> Ordering) -> [a] -> a+maximumBoundBy x f xs = maximumBy f $ x : xs +-- | The smallest element of a list with respect to the+-- given comparison function. The result is bounded by the value given as the first argument.+minimumBoundBy :: a -> (a -> a -> Ordering) -> [a] -> a+minimumBoundBy x f xs = minimumBy f $ x : xs++-- | The largest element of a list.+-- The result is bounded by the value given as the first argument.+maximumBound :: Ord a => a -> [a] -> a+maximumBound x xs = maximum $ x : xs++-- | The smallest element of a list.+-- The result is bounded by the value given as the first argument.+minimumBound :: Ord a => a -> [a] -> a+minimumBound x xs = minimum $ x : xs++-- | The largest element of a list.+-- The result is bounded by 'minBound'.+maximumBounded :: (Ord a, Bounded a) => [a] -> a+maximumBounded = maximumBound minBound++-- | The largest element of a list.+-- The result is bounded by 'maxBound'.+minimumBounded :: (Ord a, Bounded a) => [a] -> a+minimumBounded = minimumBound maxBound+ foldr1May, foldl1May, foldl1May' :: (a -> a -> a) -> [a] -> Maybe a foldr1May = liftMay null . foldr1 foldl1May = liftMay null . foldl1 foldl1May' = liftMay null . foldl1' -foldr1Def, foldl1Def, foldl1Def' :: a -> (a -> a -> a) -> [a] -> a-foldr1Def def = fromMaybe def .^ foldr1May-foldl1Def def = fromMaybe def .^ foldl1May-foldl1Def' def = fromMaybe def .^ foldl1May'- foldr1Note, foldl1Note, foldl1Note' :: Partial => String -> (a -> a -> a) -> [a] -> a foldr1Note note f x = withFrozenCallStack $ fromNote note "foldr1Note []" $ foldr1May f x foldl1Note note f x = withFrozenCallStack $ fromNote note "foldl1Note []" $ foldl1May f x@@ -344,3 +389,29 @@ indexNote :: (Partial, Ix a) => String -> (a, a) -> a -> Int indexNote note x y = withFrozenCallStack $ fromNote note "indexNote, out of range" $ indexMay x y+++---------------------------------------------------------------------+-- DISCOURAGED++-- | New users are recommended to use 'minimumBound' or 'maximumBound' instead.+minimumDef, maximumDef :: Ord a => a -> [a] -> a+minimumDef def = fromMaybe def . minimumMay+maximumDef def = fromMaybe def . maximumMay++-- | New users are recommended to use 'minimumBoundBy' or 'maximumBoundBy' instead.+minimumByDef, maximumByDef :: a -> (a -> a -> Ordering) -> [a] -> a+minimumByDef def = fromMaybe def .^ minimumByMay+maximumByDef def = fromMaybe def .^ maximumByMay+++---------------------------------------------------------------------+-- DEPRECATED++{-# DEPRECATED foldr1Def "Use @foldr1May@ instead." #-}+{-# DEPRECATED foldl1Def "Use @foldl1May@ instead." #-}+{-# DEPRECATED foldl1Def' "Use @foldl1May'@ instead." #-}+foldr1Def, foldl1Def, foldl1Def' :: a -> (a -> a -> a) -> [a] -> a+foldr1Def def = fromMaybe def .^ foldr1May+foldl1Def def = fromMaybe def .^ foldl1May+foldl1Def' def = fromMaybe def .^ foldl1May'
Safe/Exact.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE TupleSections #-} {- | Provides functions that raise errors in corner cases instead of returning \"best effort\" results, then provides wrappers like the "Safe" module. For example:@@ -95,7 +96,7 @@ -- > | n >= 0 && n <= length xs = drop n xs -- > | otherwise = error "some message" dropExact :: Partial => Int -> [a] -> [a]-dropExact i xs = withFrozenCallStack $ splitAtExact_ (addNote "" "dropExact") id (flip const) i xs+dropExact i xs = withFrozenCallStack $ splitAtExact_ (addNote "" "dropExact") id (\_ x -> x) i xs -- | -- > splitAtExact n xs =@@ -103,7 +104,7 @@ -- > | otherwise = error "some message" splitAtExact :: Partial => Int -> [a] -> ([a], [a]) splitAtExact i xs = withFrozenCallStack $ splitAtExact_ (addNote "" "splitAtExact")- (\x -> ([], x)) (\a b -> first (a:) b) i xs+ ([],) (\a b -> first (a:) b) i xs takeExactNote :: Partial => String -> Int -> [a] -> [a] takeExactNote note i xs = withFrozenCallStack $ splitAtExact_ (addNote note "takeExactNote") (const []) (:) i xs@@ -115,17 +116,17 @@ takeExactDef def = fromMaybe def .^ takeExactMay dropExactNote :: Partial => String -> Int -> [a] -> [a]-dropExactNote note i xs = withFrozenCallStack $ splitAtExact_ (addNote note "dropExactNote") id (flip const) i xs+dropExactNote note i xs = withFrozenCallStack $ splitAtExact_ (addNote note "dropExactNote") id (\_ x -> x) i xs dropExactMay :: Int -> [a] -> Maybe [a]-dropExactMay = splitAtExact_ (const Nothing) Just (flip const)+dropExactMay = splitAtExact_ (const Nothing) Just (\_ x -> x) dropExactDef :: [a] -> Int -> [a] -> [a] dropExactDef def = fromMaybe def .^ dropExactMay splitAtExactNote :: Partial => String -> Int -> [a] -> ([a], [a]) splitAtExactNote note i xs = withFrozenCallStack $ splitAtExact_ (addNote note "splitAtExactNote")- (\x -> ([], x)) (\a b -> first (a:) b) i xs+ ([],) (\a b -> first (a:) b) i xs splitAtExactMay :: Int -> [a] -> Maybe ([a], [a]) splitAtExactMay = splitAtExact_ (const Nothing)
Safe/Foldable.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE CPP #-} {-# LANGUAGE ConstraintKinds #-} {- | 'Foldable' functions, with wrappers like the "Safe" module.@@ -11,12 +10,17 @@ foldl1May, foldl1Def, foldl1Note, foldr1May, foldr1Def, foldr1Note, findJustDef, findJustNote,- minimumMay, minimumDef, minimumNote,- maximumMay, maximumDef, maximumNote,- minimumByMay, minimumByDef, minimumByNote,- maximumByMay, maximumByDef, maximumByNote,+ minimumMay, minimumNote,+ maximumMay, maximumNote,+ minimumByMay, minimumByNote,+ maximumByMay, maximumByNote,+ maximumBoundBy, minimumBoundBy,+ maximumBounded, maximumBound,+ minimumBounded, minimumBound,+ -- * Discouraged+ minimumDef, maximumDef, minimumByDef, maximumByDef, -- * Deprecated- foldl1Safe, foldr1Safe, findJustSafe+ foldl1Safe, foldr1Safe, findJustSafe, ) where import Safe.Util@@ -33,52 +37,64 @@ fromNote :: Partial => String -> String -> Maybe a -> a fromNote = fromNoteModule "Safe.Foldable" -isNull :: Foldable t => t a -> Bool-#if __GLASGOW_HASKELL__ < 710-isNull = null . toList-#else-isNull = F.null-#endif --------------------------------------------------------------------- -- WRAPPERS foldl1May, foldr1May :: Foldable t => (a -> a -> a) -> t a -> Maybe a-foldl1May = liftMay isNull . F.foldl1-foldr1May = liftMay isNull . F.foldr1+foldl1May = liftMay F.null . F.foldl1+foldr1May = liftMay F.null . F.foldr1 foldl1Note, foldr1Note :: (Partial, Foldable t) => String -> (a -> a -> a) -> t a -> a foldl1Note note f x = withFrozenCallStack $ fromNote note "foldl1Note on empty" $ foldl1May f x foldr1Note note f x = withFrozenCallStack $ fromNote note "foldr1Note on empty" $ foldr1May f x -foldl1Def, foldr1Def :: Foldable t => a -> (a -> a -> a) -> t a -> a-foldl1Def def = fromMaybe def .^ foldl1May-foldr1Def def = fromMaybe def .^ foldr1May- minimumMay, maximumMay :: (Foldable t, Ord a) => t a -> Maybe a-minimumMay = liftMay isNull F.minimum-maximumMay = liftMay isNull F.maximum--minimumDef, maximumDef :: (Foldable t, Ord a) => a -> t a -> a-minimumDef def = fromMaybe def . minimumMay-maximumDef def = fromMaybe def . maximumMay+minimumMay = liftMay F.null F.minimum+maximumMay = liftMay F.null F.maximum minimumNote, maximumNote :: (Partial, Foldable t, Ord a) => String -> t a -> a minimumNote note x = withFrozenCallStack $ fromNote note "minimumNote on empty" $ minimumMay x maximumNote note x = withFrozenCallStack $ fromNote note "maximumNote on empty" $ maximumMay x minimumByMay, maximumByMay :: Foldable t => (a -> a -> Ordering) -> t a -> Maybe a-minimumByMay = liftMay isNull . F.minimumBy-maximumByMay = liftMay isNull . F.maximumBy--minimumByDef, maximumByDef :: Foldable t => a -> (a -> a -> Ordering) -> t a -> a-minimumByDef def = fromMaybe def .^ minimumByMay-maximumByDef def = fromMaybe def .^ maximumByMay+minimumByMay = liftMay F.null . F.minimumBy+maximumByMay = liftMay F.null . F.maximumBy minimumByNote, maximumByNote :: (Partial, Foldable t) => String -> (a -> a -> Ordering) -> t a -> a minimumByNote note f x = withFrozenCallStack $ fromNote note "minimumByNote on empty" $ minimumByMay f x maximumByNote note f x = withFrozenCallStack $ fromNote note "maximumByNote on empty" $ maximumByMay f x +-- | The largest element of a foldable structure with respect to the+-- given comparison function. The result is bounded by the value given as the first argument.+maximumBoundBy :: Foldable f => a -> (a -> a -> Ordering) -> f a -> a+maximumBoundBy x f xs = maximumBy f $ x : toList xs++-- | The smallest element of a foldable structure with respect to the+-- given comparison function. The result is bounded by the value given as the first argument.+minimumBoundBy :: Foldable f => a -> (a -> a -> Ordering) -> f a -> a+minimumBoundBy x f xs = minimumBy f $ x : toList xs++-- | The largest element of a foldable structure.+-- The result is bounded by the value given as the first argument.+maximumBound :: (Foldable f, Ord a) => a -> f a -> a+maximumBound x xs = maximum $ x : toList xs++-- | The smallest element of a foldable structure.+-- The result is bounded by the value given as the first argument.+minimumBound :: (Foldable f, Ord a) => a -> f a -> a+minimumBound x xs = minimum $ x : toList xs++-- | The largest element of a foldable structure.+-- The result is bounded by 'minBound'.+maximumBounded :: (Foldable f, Ord a, Bounded a) => f a -> a+maximumBounded = maximumBound minBound++-- | The largest element of a foldable structure.+-- The result is bounded by 'maxBound'.+minimumBounded :: (Foldable f, Ord a, Bounded a) => f a -> a+minimumBounded = minimumBound maxBound+ -- | -- > findJust op = fromJust . find op findJust :: (Partial, Foldable t) => (a -> Bool) -> t a -> a@@ -92,6 +108,25 @@ ---------------------------------------------------------------------+-- DISCOURAGED++-- | New users are recommended to use 'minimumBound' or 'maximumBound' instead.+minimumDef, maximumDef :: (Foldable t, Ord a) => a -> t a -> a+minimumDef def = fromMaybe def . minimumMay+maximumDef def = fromMaybe def . maximumMay++-- | New users are recommended to use 'minimumBoundBy' or 'maximumBoundBy' instead.+minimumByDef, maximumByDef :: Foldable t => a -> (a -> a -> Ordering) -> t a -> a+minimumByDef def = fromMaybe def .^ minimumByMay+maximumByDef def = fromMaybe def .^ maximumByMay++-- | New users are recommended to use 'foldr1May' or 'foldl1May' instead.+foldl1Def, foldr1Def :: Foldable t => a -> (a -> a -> a) -> t a -> a+foldl1Def def = fromMaybe def .^ foldl1May+foldr1Def def = fromMaybe def .^ foldr1May+++--------------------------------------------------------------------- -- DEPRECATED {-# DEPRECATED foldl1Safe "Use @foldl f mempty@ instead." #-}@@ -101,7 +136,6 @@ {-# DEPRECATED foldr1Safe "Use @foldr f mempty@ instead." #-} foldr1Safe :: (Monoid m, Foldable t) => (m -> m -> m) -> t m -> m foldr1Safe fun = F.foldr fun mempty- {-# DEPRECATED findJustSafe "Use @findJustDef mempty@ instead." #-} findJustSafe :: (Monoid m, Foldable t) => (m -> Bool) -> t m -> m
safe.cabal view
@@ -1,17 +1,17 @@-cabal-version: >= 1.18+cabal-version: 1.18 build-type: Simple name: safe-version: 0.3.17+version: 0.3.21 license: BSD3 license-file: LICENSE category: Unclassified author: Neil Mitchell <ndmitchell@gmail.com> maintainer: Neil Mitchell <ndmitchell@gmail.com>-copyright: Neil Mitchell 2007-2018+copyright: Neil Mitchell 2007-2024 homepage: https://github.com/ndmitchell/safe#readme synopsis: Library of safe (exception free) functions bug-reports: https://github.com/ndmitchell/safe/issues-tested-with: GHC==8.2.2, GHC==8.0.2, GHC==7.10.3, GHC==7.8.4, GHC==7.6.3, GHC==7.4.2+tested-with: GHC==9.8, GHC==9.6, GHC==9.4, GHC==9.2, GHC==9.0, GHC==8.10, GHC==8.8 description: A library wrapping @Prelude@/@Data.List@ functions that can throw exceptions, such as @head@ and @!!@. Each unsafe function has up to four variants, e.g. with @tail@:@@ -44,7 +44,7 @@ library default-language: Haskell2010 build-depends:- base >= 4.5 && < 5+ base >= 4.8 && < 5 exposed-modules: Safe