packages feed

safe 0.3.15 → 0.3.21

raw patch · 9 files changed

Files

CHANGES.txt view
@@ -1,42 +1,58 @@ Changelog for Safe -0.3.15+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+0.3.16, released 2018-01-06+    #22, add Safe index+0.3.15, released 2017-06-18     Support QuickCheck 2.10-0.3.14+0.3.14, released 2017-02-15     #20, fix for GHC 7.10.1-0.3.13+0.3.13, released 2017-02-09     #20, require GHC 7.4 or above-0.3.12+0.3.12, released 2017-02-05     #19, add Safe.Partial exposing a Partial typeclass     #19, add support for GHC call stacks-0.3.11+0.3.11, released 2017-01-22     #16, add Safe succ and pred     #16, add readEitherSafe for better errors than readEither     #14, add Safe zip3Exact-0.3.10+0.3.10, released 2016-11-08     #15, add Safe cycle-0.3.9+0.3.9, released 2015-05-09     #9, add Safe toEnum-0.3.8+0.3.8, released 2014-08-10     #8, remove unnecessary Ord constraints from Foldable functions-0.3.7+0.3.7, released 2014-07-16     Add Def variants of the Exact functions-0.3.6+0.3.6, released 2014-07-12     #6, remove unnecessary Ord constraints from maximumBy/minimumBy-0.3.5+0.3.5, released 2014-06-28     Add Safe elemIndexJust/findIndexJust functions     Add Safe scan functions     Add Safe minimumBy/maximumBy functions     Add a module of Exact functions     Add Foldable minimum functions     Clean up the Foldable module, deprecate the Safe variants-0.3.4+0.3.4, released 2014-01-30     #1, improve the string clipping in readNote-0.3.3+0.3.3, released 2011-11-15     #494, add foldl1' wrappings-0.3.2+0.3.2, released 2011-11-13     Add a Safe.Foldable module-0.3.1+0.3.1, released 2011-11-09     Add findJust, safe wrapping of fromJust/find-0.3+0.3, released 2010-11-10     Start of changelog
LICENSE view
@@ -1,4 +1,4 @@-Copyright Neil Mitchell 2007-2017.+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 [![Hackage version](https://img.shields.io/hackage/v/safe.svg?label=Hackage)](https://hackage.haskell.org/package/safe) [![Build Status](https://img.shields.io/travis/ndmitchell/safe.svg)](https://travis-ci.org/ndmitchell/safe)+# Safe [![Hackage version](https://img.shields.io/hackage/v/safe.svg?label=Hackage)](https://hackage.haskell.org/package/safe) [![Stackage version](https://www.stackage.org/package/safe/badge/nightly?label=Stackage)](https://www.stackage.org/package/safe) [![Build status](https://img.shields.io/github/actions/workflow/status/ndmitchell/safe/ci.yml?branch=master)](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',@@ -49,9 +59,13 @@     toEnumMay, toEnumDef, toEnumNote, toEnumSafe,     succMay, succDef, succNote, succSafe,     predMay, predDef, predNote, predSafe,+    indexMay, indexDef, indexNote,+    -- * Discouraged+    minimumDef, maximumDef, minimumByDef, maximumByDef     ) where  import Safe.Util+import Data.Ix import Data.List import Data.Maybe import Safe.Partial@@ -73,7 +87,7 @@ --   has decided to exit because of invalid user input, or the user pressed --   quit etc. This function allows 'error' to be reserved for programmer errors. abort :: Partial => String -> a-abort = error+abort x = withFrozenCallStack (error x)   at_ :: [a] -> Int -> Either String a@@ -87,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]@@ -103,7 +134,7 @@ -- > tailNote "help me" [] = error "Safe.tailNote [], help me" -- > tailNote "help me" [1,3,4] = [3,4] tailNote :: Partial => String -> [a] -> [a]-tailNote note = fromNote note "tailNote []" . tailMay+tailNote note x = withFrozenCallStack $ fromNote note "tailNote []" $ tailMay x  -- | -- > tailSafe [] = []@@ -119,7 +150,7 @@ initDef def = fromMaybe def . initMay  initNote :: Partial => String -> [a] -> [a]-initNote note = fromNote note "initNote []" . initMay+initNote note x = withFrozenCallStack $ fromNote note "initNote []" $ initMay x  initSafe :: [a] -> [a] initSafe = initDef []@@ -127,56 +158,72 @@   headMay, lastMay :: [a] -> Maybe a-headMay = liftMay null head+headMay = listToMaybe lastMay = liftMay null last  headDef, lastDef :: a -> [a] -> a headDef def = fromMaybe def . headMay lastDef def = fromMaybe def . lastMay -headNote, lastNote :: String -> [a] -> a-headNote note = fromNote note "headNote []" . headMay-lastNote note = fromNote note "lastNote []" . lastMay+headNote, lastNote :: Partial => String -> [a] -> a+headNote note x = withFrozenCallStack $ fromNote note "headNote []" $ headMay x+lastNote note x = withFrozenCallStack $ fromNote note "lastNote []" $ lastMay x  minimumMay, maximumMay :: Ord a => [a] -> Maybe a 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 = fromNote note "minumumNote []" . minimumMay-maximumNote note = fromNote note "maximumNote []" . maximumMay+minimumNote note x = withFrozenCallStack $ fromNote note "minumumNote []" $ minimumMay x+maximumNote note x = withFrozenCallStack $ fromNote note "maximumNote []" $ maximumMay x  minimumByMay, maximumByMay :: (a -> a -> Ordering) -> [a] -> Maybe a 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 = fromNote note "minumumByNote []" .^ minimumByMay-maximumByNote note = fromNote note "maximumByNote []" .^ maximumByMay+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 = fromNote note "foldr1Note []" .^ foldr1May-foldl1Note note = fromNote note "foldl1Note []" .^ foldl1May-foldl1Note' note = fromNote note "foldl1Note []" .^ foldl1May'+foldr1Note note f x = withFrozenCallStack $ fromNote note "foldr1Note []" $ foldr1May f x+foldl1Note note f x = withFrozenCallStack $ fromNote note "foldl1Note []" $ foldl1May f x+foldl1Note' note f x = withFrozenCallStack $ fromNote note "foldl1Note []" $ foldl1May' f x  scanr1May, scanl1May :: (a -> a -> a) -> [a] -> Maybe [a] scanr1May = liftMay null . scanr1@@ -187,8 +234,8 @@ scanl1Def def = fromMaybe def .^ scanl1May  scanr1Note, scanl1Note :: Partial => String -> (a -> a -> a) -> [a] -> [a]-scanr1Note note = fromNote note "scanr1Note []" .^ scanr1May-scanl1Note note = fromNote note "scanl1Note []" .^ scanl1May+scanr1Note note f x = withFrozenCallStack $ fromNote note "scanr1Note []" $ scanr1May f x+scanl1Note note f x = withFrozenCallStack $ fromNote note "scanl1Note []" $ scanl1May f x  cycleMay :: [a] -> Maybe [a] cycleMay = liftMay null cycle@@ -197,7 +244,7 @@ cycleDef def = fromMaybe def . cycleMay  cycleNote :: Partial => String -> [a] -> [a]-cycleNote note = fromNote note "cycleNote []" . cycleMay+cycleNote note x = withFrozenCallStack $ fromNote note "cycleNote []" $ cycleMay x  -- | An alternative name for 'fromMaybe', to fit the naming scheme of this package. --   Generally using 'fromMaybe' directly would be considered better style.@@ -205,11 +252,11 @@ fromJustDef  = fromMaybe  fromJustNote :: Partial => String -> Maybe a -> a-fromJustNote note = fromNote note "fromJustNote Nothing"+fromJustNote note x = withFrozenCallStack $ fromNote note "fromJustNote Nothing" x  assertNote :: Partial => String -> Bool -> a -> a assertNote note True val = val-assertNote note False val = fromNote note "assertNote False" Nothing+assertNote note False val = withFrozenCallStack $ fromNote note "assertNote False" Nothing   -- | Synonym for '!!', but includes more information in the error message.@@ -223,7 +270,7 @@ atDef def = fromMaybe def .^ atMay  atNote :: Partial => String -> [a] -> Int -> a-atNote note = fromNoteEither note "atNote" .^ at_+atNote note f x = withFrozenCallStack $ fromNoteEither note "atNote" $ at_ f x  -- | This function provides a more precise error message than 'readEither' from 'base'. readEitherSafe :: Read a => String -> Either String a@@ -244,18 +291,18 @@  -- | 'readNote' uses 'readEitherSafe' for the error message. readNote :: (Partial, Read a) => String -> String -> a-readNote note = fromNoteEither note "readNote" . readEitherSafe+readNote note x = withFrozenCallStack $ fromNoteEither note "readNote" $ readEitherSafe x  -- | -- > lookupJust key = fromJust . lookup key-lookupJust :: Eq a => a -> [(a,b)] -> b-lookupJust = fromNote "" "lookupJust, no matching value" .^ lookup+lookupJust :: (Eq a, Partial) => a -> [(a,b)] -> b+lookupJust x xs = withFrozenCallStack $ fromNote "" "lookupJust, no matching value" $ lookup x xs  lookupJustDef :: Eq a => b -> a -> [(a,b)] -> b lookupJustDef def = fromMaybe def .^ lookup  lookupJustNote :: (Partial, Eq a) => String -> a -> [(a,b)] -> b-lookupJustNote note = fromNote note "lookupJustNote, no matching value" .^ lookup+lookupJustNote note x xs = withFrozenCallStack $ fromNote note "lookupJustNote, no matching value" $ lookup x xs  -- | -- > findJust op = fromJust . find op@@ -266,29 +313,29 @@ findJustDef def = fromMaybe def .^ find  findJustNote :: Partial => String -> (a -> Bool) -> [a] -> a-findJustNote note = fromNote note "findJustNote, no matching value" .^ find+findJustNote note f x = withFrozenCallStack $ fromNote note "findJustNote, no matching value" $ find f x  -- | -- > elemIndexJust op = fromJust . elemIndex op-elemIndexJust :: Eq a => a -> [a] -> Int-elemIndexJust = fromNote "" "elemIndexJust, no matching value" .^ elemIndex+elemIndexJust :: (Partial, Eq a) => a -> [a] -> Int+elemIndexJust x xs = withFrozenCallStack $ fromNote "" "elemIndexJust, no matching value" $ elemIndex x xs  elemIndexJustDef :: Eq a => Int -> a -> [a] -> Int elemIndexJustDef def = fromMaybe def .^ elemIndex  elemIndexJustNote :: (Partial, Eq a) => String -> a -> [a] -> Int-elemIndexJustNote note = fromNote note "elemIndexJustNote, no matching value" .^ elemIndex+elemIndexJustNote note x xs = withFrozenCallStack $ fromNote note "elemIndexJustNote, no matching value" $ elemIndex x xs  -- | -- > findIndexJust op = fromJust . findIndex op findIndexJust :: (a -> Bool) -> [a] -> Int-findIndexJust = fromNote "" "findIndexJust, no matching value" .^ findIndex+findIndexJust f x = withFrozenCallStack $ fromNote "" "findIndexJust, no matching value" $ findIndex f x  findIndexJustDef :: Int -> (a -> Bool) -> [a] -> Int findIndexJustDef def = fromMaybe def .^ findIndex  findIndexJustNote :: Partial => String -> (a -> Bool) -> [a] -> Int-findIndexJustNote note = fromNote note "findIndexJustNote, no matching value" .^ findIndex+findIndexJustNote note f x = withFrozenCallStack $ fromNote note "findIndexJustNote, no matching value" $ findIndex f x  -- From http://stackoverflow.com/questions/2743858/safe-and-polymorphic-toenum -- answer by C. A. McCann@@ -305,7 +352,7 @@ toEnumDef def = fromMaybe def . toEnumMay  toEnumNote :: (Partial, Enum a, Bounded a) => String -> Int -> a-toEnumNote note = fromNote note "toEnumNote, out of range" . toEnumMay+toEnumNote note x = withFrozenCallStack $ fromNote note "toEnumNote, out of range" $ toEnumMay x  toEnumSafe :: (Enum a, Bounded a) => Int -> a toEnumSafe = toEnumDef minBound@@ -317,7 +364,7 @@ succDef def = fromMaybe def . succMay  succNote :: (Partial, Enum a, Eq a, Bounded a) => String -> a -> a-succNote note = fromNote note "succNote, out of range" . succMay+succNote note x = withFrozenCallStack $ fromNote note "succNote, out of range" $ succMay x  succSafe :: (Enum a, Eq a, Bounded a) => a -> a succSafe = succDef maxBound@@ -329,7 +376,42 @@ predDef def = fromMaybe def . predMay  predNote :: (Partial, Enum a, Eq a, Bounded a) => String -> a -> a-predNote note = fromNote note "predNote, out of range" . predMay+predNote note x = withFrozenCallStack $ fromNote note "predNote, out of range" $ predMay x  predSafe :: (Enum a, Eq a, Bounded a) => a -> a predSafe = predDef minBound++indexMay :: Ix a => (a, a) -> a -> Maybe Int+indexMay b i = if inRange b i then Just (index b i) else Nothing++indexDef :: Ix a => Int -> (a, a) -> a -> Int+indexDef def b = fromMaybe def . indexMay b++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:@@ -88,25 +89,25 @@ -- >   | n >= 0 && n <= length xs = take n xs -- >   | otherwise                = error "some message" takeExact :: Partial => Int -> [a] -> [a]-takeExact = splitAtExact_ (addNote "" "takeExact") (const []) (:)+takeExact i xs = withFrozenCallStack $ splitAtExact_ (addNote "" "takeExact") (const []) (:) i xs  -- | -- > dropExact n xs = -- >   | n >= 0 && n <= length xs = drop n xs -- >   | otherwise                = error "some message" dropExact :: Partial => Int -> [a] -> [a]-dropExact = splitAtExact_ (addNote "" "dropExact") id (flip const)+dropExact i xs = withFrozenCallStack $ splitAtExact_ (addNote "" "dropExact") id (\_ x -> x) i xs  -- | -- > splitAtExact n xs = -- >   | n >= 0 && n <= length xs = splitAt n xs -- >   | otherwise                = error "some message" splitAtExact :: Partial => Int -> [a] -> ([a], [a])-splitAtExact = splitAtExact_ (addNote "" "splitAtExact")-    (\x -> ([], x)) (\a b -> first (a:) b)+splitAtExact i xs = withFrozenCallStack $ splitAtExact_ (addNote "" "splitAtExact")+    ([],) (\a b -> first (a:) b) i xs  takeExactNote :: Partial => String -> Int -> [a] -> [a]-takeExactNote note = splitAtExact_ (addNote note "takeExactNote") (const []) (:)+takeExactNote note i xs = withFrozenCallStack $ splitAtExact_ (addNote note "takeExactNote") (const []) (:) i xs  takeExactMay :: Int -> [a] -> Maybe [a] takeExactMay = splitAtExact_ (const Nothing) (const $ Just []) (\a -> fmap (a:))@@ -115,17 +116,17 @@ takeExactDef def = fromMaybe def .^ takeExactMay  dropExactNote :: Partial => String -> Int -> [a] -> [a]-dropExactNote note = splitAtExact_ (addNote note "dropExactNote") id (flip const)+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 = splitAtExact_ (addNote note "splitAtExactNote")-    (\x -> ([], x)) (\a b -> first (a:) b)+splitAtExactNote note i xs = withFrozenCallStack $ splitAtExact_ (addNote note "splitAtExactNote")+    ([],) (\a b -> first (a:) b) i xs  splitAtExactMay :: Int -> [a] -> Maybe ([a], [a]) splitAtExactMay = splitAtExact_ (const Nothing)@@ -142,18 +143,18 @@ -- >   | length xs == length ys = zip xs ys -- >   | otherwise              = error "some message" zipExact :: Partial => [a] -> [b] -> [(a,b)]-zipExact = zipWithExact_ (addNote "" "zipExact") []  (\a b xs -> (a,b) : xs)+zipExact xs ys = withFrozenCallStack $ zipWithExact_ (addNote "" "zipExact") []  (\a b xs -> (a,b) : xs) xs ys  -- | -- > zipWithExact f xs ys = -- >   | length xs == length ys = zipWith f xs ys -- >   | otherwise              = error "some message" zipWithExact :: Partial => (a -> b -> c) -> [a] -> [b] -> [c]-zipWithExact f = zipWithExact_ (addNote "" "zipWithExact") [] (\a b xs -> f a b : xs)+zipWithExact f xs ys = withFrozenCallStack $ zipWithExact_ (addNote "" "zipWithExact") [] (\a b xs -> f a b : xs) xs ys   zipExactNote :: Partial => String -> [a] -> [b] -> [(a,b)]-zipExactNote note = zipWithExact_ (addNote note "zipExactNote") []  (\a b xs -> (a,b) : xs)+zipExactNote note xs ys = withFrozenCallStack $ zipWithExact_ (addNote note "zipExactNote") []  (\a b xs -> (a,b) : xs) xs ys  zipExactMay :: [a] -> [b] -> Maybe [(a,b)] zipExactMay = zipWithExact_ (const Nothing) (Just [])  (\a b xs -> fmap ((a,b) :) xs)@@ -162,7 +163,7 @@ zipExactDef def = fromMaybe def .^ zipExactMay  zipWithExactNote :: Partial => String -> (a -> b -> c) -> [a] -> [b] -> [c]-zipWithExactNote note f = zipWithExact_ (addNote note "zipWithExactNote") []  (\a b xs -> f a b : xs)+zipWithExactNote note f xs ys = withFrozenCallStack $ zipWithExact_ (addNote note "zipWithExactNote") []  (\a b xs -> f a b : xs) xs ys  zipWithExactMay :: (a -> b -> c) -> [a] -> [b] -> Maybe [c] zipWithExactMay f = zipWithExact_ (const Nothing) (Just [])  (\a b xs -> fmap (f a b :) xs)@@ -176,18 +177,18 @@ -- >   | length xs == length ys && length xs == length zs = zip3 xs ys zs -- >   | otherwise                                        = error "some message" zip3Exact :: Partial => [a] -> [b] -> [c] -> [(a,b,c)]-zip3Exact = zipWith3Exact_ (addNote "" "zip3Exact") [] (\a b c xs -> (a, b, c) : xs)+zip3Exact xs ys zs = withFrozenCallStack $ zipWith3Exact_ (addNote "" "zip3Exact") [] (\a b c xs -> (a, b, c) : xs) xs ys zs  -- | -- > zipWith3Exact f xs ys zs = -- >   | length xs == length ys && length xs == length zs = zipWith3 f xs ys zs -- >   | otherwise                                        = error "some message" zipWith3Exact :: Partial => (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]-zipWith3Exact f = zipWith3Exact_ (addNote "" "zipWith3Exact") [] (\a b c xs -> f a b c : xs)+zipWith3Exact f xs ys zs = withFrozenCallStack $ zipWith3Exact_ (addNote "" "zipWith3Exact") [] (\a b c xs -> f a b c : xs) xs ys zs   zip3ExactNote :: Partial => String -> [a] -> [b] -> [c]-> [(a,b,c)]-zip3ExactNote note = zipWith3Exact_ (addNote note "zip3ExactNote") [] (\a b c xs -> (a,b,c) : xs)+zip3ExactNote note xs ys zs = withFrozenCallStack $ zipWith3Exact_ (addNote note "zip3ExactNote") [] (\a b c xs -> (a,b,c) : xs) xs ys zs  zip3ExactMay :: [a] -> [b] -> [c] -> Maybe [(a,b,c)] zip3ExactMay = zipWith3Exact_ (const Nothing) (Just [])  (\a b c xs -> fmap ((a,b,c) :) xs)@@ -196,7 +197,7 @@ zip3ExactDef def = fromMaybe def .^^ zip3ExactMay  zipWith3ExactNote :: Partial => String -> (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]-zipWith3ExactNote note f = zipWith3Exact_ (addNote note "zipWith3ExactNote") []  (\a b c xs -> f a b c : xs)+zipWith3ExactNote note f xs ys zs = withFrozenCallStack $ zipWith3Exact_ (addNote note "zipWith3ExactNote") []  (\a b c xs -> f a b c : xs) xs ys zs  zipWith3ExactMay :: (a -> b -> c -> d) -> [a] -> [b] -> [c] -> Maybe [d] zipWith3ExactMay f = zipWith3Exact_ (const Nothing) (Just [])  (\a b c xs -> fmap (f a b c :) xs)
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,65 +37,96 @@ 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 = fromNote note "foldl1Note on empty" .^ foldl1May-foldr1Note note = fromNote note "foldr1Note on empty" .^ foldr1May--foldl1Def, foldr1Def :: Foldable t => a -> (a -> a -> a) -> t a -> a-foldl1Def def = fromMaybe def .^ foldl1May-foldr1Def def = fromMaybe def .^ foldr1May+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  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 = fromNote note "minimumNote on empty" . minimumMay-maximumNote note = fromNote note "maximumNote on empty" . maximumMay+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 = fromNote note "minimumByNote on empty" .^ minimumByMay-maximumByNote note = fromNote note "maximumByNote on empty" .^ maximumByMay+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-findJust = fromNote "" "findJust, no matching value" .^ F.find+findJust f x = withFrozenCallStack $ fromNote "" "findJust, no matching value" $ F.find f x  findJustDef :: Foldable t => a -> (a -> Bool) -> t a -> a findJustDef def = fromMaybe def .^ F.find  findJustNote :: (Partial, Foldable t) => String -> (a -> Bool) -> t a -> a-findJustNote note = fromNote note "findJustNote, no matching value" .^ F.find+findJustNote note f x = withFrozenCallStack $ fromNote note "findJustNote, no matching value" $ F.find f x   ---------------------------------------------------------------------+-- 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/Util.hs view
@@ -1,10 +1,26 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ConstraintKinds  #-}+{-# LANGUAGE CPP              #-}+ -- | Internal utilities.-module Safe.Util where+module Safe.Util(+    fromNoteModule, fromNoteEitherModule,+    liftMay,+    (.^), (.^^), (.^^^),+    eitherToMaybe,+    withFrozenCallStack+    ) where  import Data.Maybe import Safe.Partial++-- Let things work through ghci alone+#if __GLASGOW_HASKELL__ >= 800+import GHC.Stack+#else+withFrozenCallStack :: a -> a+withFrozenCallStack = id+#endif   (.^) :: Partial => (b -> c) -> (a1 -> a2 -> b) -> a1 -> a2 -> c
Test.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE ScopedTypeVariables #-}+{-# OPTIONS_GHC -fno-warn-orphans #-} -- In the test suite, so OK  module Main(main) where 
safe.cabal view
@@ -1,17 +1,17 @@-cabal-version:  >= 1.18+cabal-version:  1.18 build-type:     Simple name:           safe-version:        0.3.15+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-2017+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.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@@ -60,6 +60,12 @@     main-is:            Test.hs     default-language:   Haskell2010 +    other-modules:+        Safe+        Safe.Exact+        Safe.Foldable+        Safe.Partial+        Safe.Util     build-depends:         base,         deepseq,