extra 1.6.17 → 1.6.18
raw patch · 5 files changed
+47/−10 lines, 5 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Data.List.Extra: maximumOn :: Ord b => (a -> b) -> [a] -> a
+ Data.List.Extra: maximumOn :: (Partial, Ord b) => (a -> b) -> [a] -> a
- Data.List.Extra: minimumOn :: Ord b => (a -> b) -> [a] -> a
+ Data.List.Extra: minimumOn :: (Partial, Ord b) => (a -> b) -> [a] -> a
- Extra: maximumOn :: Ord b => (a -> b) -> [a] -> a
+ Extra: maximumOn :: (Partial, Ord b) => (a -> b) -> [a] -> a
- Extra: minimumOn :: Ord b => (a -> b) -> [a] -> a
+ Extra: minimumOn :: (Partial, Ord b) => (a -> b) -> [a] -> a
Files
- CHANGES.txt +3/−0
- extra.cabal +1/−1
- src/Control/Exception/Extra.hs +12/−3
- src/Data/List/Extra.hs +26/−5
- test/TestGen.hs +5/−1
CHANGES.txt view
@@ -1,5 +1,8 @@ Changelog for Extra +1.6.18, released 2019-08-21+ Make errorIO include a call stack+ Make maximumOn and minimumOn apply the function once per element 1.6.17, released 2019-05-31 Add enumerate 1.6.16, released 2019-05-25
extra.cabal view
@@ -1,7 +1,7 @@ cabal-version: >= 1.18 build-type: Simple name: extra-version: 1.6.17+version: 1.6.18 license: BSD3 license-file: LICENSE category: Development
src/Control/Exception/Extra.hs view
@@ -21,6 +21,10 @@ catchBool, handleBool, tryBool ) where +#if __GLASGOW_HASKELL__ >= 800+import GHC.Stack+#endif+ import Control.Exception import Control.Monad import Data.List.Extra@@ -68,11 +72,16 @@ -- | Like error, but in the 'IO' monad.--- Note that while 'fail' in 'IO' raises an 'IOException', this function raises an 'ErrorCall' exception.+-- Note that while 'fail' in 'IO' raises an 'IOException', this function raises an 'ErrorCall' exception with a call stack. ----- > try (errorIO "Hello") == return (Left (ErrorCall "Hello"))+-- > catch (errorIO "Hello") (\(ErrorCall x) -> return x) == return "Hello" errorIO :: Partial => String -> IO a-errorIO = throwIO . ErrorCall+errorIO x = withFrozenCallStack $ evaluate $ error x++#if __GLASGOW_HASKELL__ < 800+withFrozenCallStack :: a -> a+withFrozenCallStack = id+#endif -- | Retry an operation at most /n/ times (/n/ must be positive).
src/Data/List/Extra.hs view
@@ -364,12 +364,33 @@ nubOn f = map snd . nubBy ((==) `on` fst) . map (\x -> let y = f x in y `seq` (y, x)) -- | A version of 'maximum' where the comparison is done on some extracted value.-maximumOn :: Ord b => (a -> b) -> [a] -> a-maximumOn f = maximumBy (compare `on` f)+-- Raises an error if the list is empty. Only calls the function once per element.+--+-- > maximumOn id [] == undefined+-- > maximumOn length ["test","extra","a"] == "extra"+maximumOn :: (Partial, Ord b) => (a -> b) -> [a] -> a+maximumOn f [] = error "Data.List.Extra.maximumOn: empty list"+maximumOn f (x:xs) = g x (f x) xs+ where+ g v mv [] = v+ g v mv (x:xs) | mx > mv = g x mx xs+ | otherwise = g v mv xs+ where mx = f x --- | A version of 'minimum' where the comparison is done on some extracted value.-minimumOn :: Ord b => (a -> b) -> [a] -> a-minimumOn f = minimumBy (compare `on` f)++-- | A version of 'maximum' where the comparison is done on some extracted value.+-- Raises an error if the list is empty. Only calls the function once per element.+--+-- > minimumOn id [] == undefined+-- > minimumOn length ["test","extra","a"] == "a"+minimumOn :: (Partial, Ord b) => (a -> b) -> [a] -> a+minimumOn f [] = error "Data.List.Extra.minimumOn: empty list"+minimumOn f (x:xs) = g x (f x) xs+ where+ g v mv [] = v+ g v mv (x:xs) | mx < mv = g x mx xs+ | otherwise = g v mv xs+ where mx = f x -- | A combination of 'group' and 'sort'. --
test/TestGen.hs view
@@ -20,7 +20,7 @@ testGen "stringException ['t','e','s','t',undefined] == return \"test<Exception>\"" $ stringException ['t','e','s','t',undefined] == return "test<Exception>" testGen "ignore (print 1) == print 1" $ ignore (print 1) == print 1 testGen "ignore (fail \"die\") == return ()" $ ignore (fail "die") == return ()- testGen "try (errorIO \"Hello\") == return (Left (ErrorCall \"Hello\"))" $ try (errorIO "Hello") == return (Left (ErrorCall "Hello"))+ testGen "catch (errorIO \"Hello\") (\\(ErrorCall x) -> return x) == return \"Hello\"" $ catch (errorIO "Hello") (\(ErrorCall x) -> return x) == return "Hello" testGen "retry 1 (print \"x\") == print \"x\"" $ retry 1 (print "x") == print "x" testGen "retry 3 (fail \"die\") == fail \"die\"" $ retry 3 (fail "die") == fail "die" testGen "whenJust Nothing print == return ()" $ whenJust Nothing print == return ()@@ -149,6 +149,10 @@ testGen "escapeJSON \"\\ttab\\nnewline\\\\\" == \"\\\\ttab\\\\nnewline\\\\\\\\\"" $ escapeJSON "\ttab\nnewline\\" == "\\ttab\\nnewline\\\\" testGen "escapeJSON \"\\ESC[0mHello\" == \"\\\\u001b[0mHello\"" $ escapeJSON "\ESC[0mHello" == "\\u001b[0mHello" testGen "\\xs -> unescapeJSON (escapeJSON xs) == xs" $ \xs -> unescapeJSON (escapeJSON xs) == xs+ testGen "maximumOn id [] == undefined" $ erroneous $ maximumOn id []+ testGen "maximumOn length [\"test\",\"extra\",\"a\"] == \"extra\"" $ maximumOn length ["test","extra","a"] == "extra"+ testGen "minimumOn id [] == undefined" $ erroneous $ minimumOn id []+ testGen "minimumOn length [\"test\",\"extra\",\"a\"] == \"a\"" $ minimumOn length ["test","extra","a"] == "a" testGen "groupSort [(1,'t'),(3,'t'),(2,'e'),(2,'s')] == [(1,\"t\"),(2,\"es\"),(3,\"t\")]" $ groupSort [(1,'t'),(3,'t'),(2,'e'),(2,'s')] == [(1,"t"),(2,"es"),(3,"t")] testGen "\\xs -> map fst (groupSort xs) == sort (nub (map fst xs))" $ \xs -> map fst (groupSort xs) == sort (nub (map fst xs)) testGen "\\xs -> concatMap snd (groupSort xs) == map snd (sortOn fst xs)" $ \xs -> concatMap snd (groupSort xs) == map snd (sortOn fst xs)