extra 1.6.18 → 1.6.19
raw patch · 9 files changed
+55/−12 lines, 9 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Data.List.Extra: dropEnd1 :: [a] -> [a]
+ Data.List.Extra: headDef :: a -> [a] -> a
+ Data.List.Extra: lastDef :: a -> [a] -> a
+ Extra: dropEnd1 :: [a] -> [a]
+ Extra: headDef :: a -> [a] -> a
+ Extra: lastDef :: a -> [a] -> a
Files
- CHANGES.txt +2/−0
- LICENSE +1/−1
- extra.cabal +3/−3
- src/Control/Exception/Extra.hs +2/−1
- src/Control/Monad/Extra.hs +2/−4
- src/Data/List/Extra.hs +33/−2
- src/Extra.hs +1/−1
- test/TestGen.hs +10/−0
- test/TestUtil.hs +1/−0
CHANGES.txt view
@@ -1,5 +1,7 @@ Changelog for Extra +1.6.19, released 2020-02-11+ #50, add headDef, lastDef, and dropEnd1 1.6.18, released 2019-08-21 Make errorIO include a call stack Make maximumOn and minimumOn apply the function once per element
LICENSE view
@@ -1,4 +1,4 @@-Copyright Neil Mitchell 2014-2019.+Copyright Neil Mitchell 2014-2020. All rights reserved. Redistribution and use in source and binary forms, with or without
extra.cabal view
@@ -1,13 +1,13 @@ cabal-version: >= 1.18 build-type: Simple name: extra-version: 1.6.18+version: 1.6.19 license: BSD3 license-file: LICENSE category: Development author: Neil Mitchell <ndmitchell@gmail.com> maintainer: Neil Mitchell <ndmitchell@gmail.com>-copyright: Neil Mitchell 2014-2019+copyright: Neil Mitchell 2014-2020 synopsis: Extra functions I use. description: A library of extra functions for the standard Haskell libraries. Most functions are simple additions, filling out missing functionality. A few functions are available in later versions of GHC, but this package makes them available back to GHC 7.2.@@ -15,7 +15,7 @@ The module "Extra" documents all functions provided by this library. Modules such as "Data.List.Extra" provide extra functions over "Data.List" and also reexport "Data.List". Users are recommended to replace "Data.List" imports with "Data.List.Extra" if they need the extra functionality. homepage: https://github.com/ndmitchell/extra#readme bug-reports: https://github.com/ndmitchell/extra/issues-tested-with: GHC==8.6.5, GHC==8.4.4, GHC==8.2.2, GHC==8.0.2, GHC==7.10.3+tested-with: GHC==8.8.1, GHC==8.6.5, GHC==8.4.4, GHC==8.2.2, GHC==8.0.2, GHC==7.10.3 extra-doc-files: CHANGES.txt
src/Control/Exception/Extra.hs view
@@ -71,10 +71,11 @@ ignore = void . try_ --- | Like error, but in the 'IO' monad.+-- | An 'IO' action that when evaluated calls 'error', in the 'IO' monad. -- Note that while 'fail' in 'IO' raises an 'IOException', this function raises an 'ErrorCall' exception with a call stack. -- -- > catch (errorIO "Hello") (\(ErrorCall x) -> return x) == return "Hello"+-- > seq (errorIO "foo") (print 1) == print 1 errorIO :: Partial => String -> IO a errorIO x = withFrozenCallStack $ evaluate $ error x
src/Control/Monad/Extra.hs view
@@ -204,8 +204,7 @@ -- > anyM Just [False,False,undefined] == undefined -- > \(f :: Int -> Maybe Bool) xs -> anyM f xs == orM (map f xs) anyM :: Monad m => (a -> m Bool) -> [a] -> m Bool-anyM p [] = return False-anyM p (x:xs) = ifM (p x) (return True) (anyM p xs)+anyM p = foldr (\x -> ifM (p x) (return True)) (return False) -- | A version of 'all' lifted to a monad. Retains the short-circuiting behaviour. --@@ -240,8 +239,7 @@ -- > findM (Just . isUpper) "test" == Just Nothing -- > findM (Just . const True) ["x",undefined] == Just (Just "x") findM :: Monad m => (a -> m Bool) -> [a] -> m (Maybe a)-findM p [] = return Nothing-findM p (x:xs) = ifM (p x) (return $ Just x) (findM p xs)+findM p = foldr (\x -> ifM (p x) (return $ Just x)) (return Nothing) -- | Like 'findM', but also allows you to compute some additional information in the predicate. firstJustM :: Monad m => (a -> m (Maybe b)) -> [a] -> m (Maybe b)
src/Data/List/Extra.hs view
@@ -18,7 +18,8 @@ wordsBy, linesBy, breakOn, breakOnEnd, splitOn, split, chunksOf, -- * Basics- notNull, list, unsnoc, cons, snoc, drop1, mconcatMap,+ headDef, lastDef, notNull, list, unsnoc, cons, snoc,+ drop1, dropEnd1, mconcatMap, -- * Enum operations enumerate, -- * List operations@@ -98,6 +99,26 @@ allSame (x:xs) = all (x ==) xs +-- | A total 'head' with a default value.+--+-- > headDef 1 [] == 1+-- > headDef 1 [2,3,4] == 2+-- > \x xs -> headDef x xs == fromMaybe x (listToMaybe xs)+headDef :: a -> [a] -> a+headDef d [] = d+headDef _ (x:_) = x+++-- | A total 'last' with a default value.+--+-- > lastDef 1 [] == 1+-- > lastDef 1 [2,3,4] == 4+-- > \x xs -> lastDef x xs == last (x:xs)+lastDef :: a -> [a] -> a+lastDef d xs = foldl (\_ x -> x) d xs -- I know this looks weird, but apparently this is the fastest way to do this: https://hackage.haskell.org/package/base-4.12.0.0/docs/src/GHC.List.html#last+{-# INLINE lastDef #-}++ -- | A composition of 'not' and 'null'. -- -- > notNull [] == False@@ -378,7 +399,7 @@ where mx = f x --- | A version of 'maximum' where the comparison is done on some extracted value.+-- | A version of 'minimum' 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@@ -508,6 +529,16 @@ drop1 :: [a] -> [a] drop1 [] = [] drop1 (x:xs) = xs+++-- | Equivalent to @dropEnd 1@, but likely to be faster and a single lexeme.+--+-- > dropEnd1 "" == ""+-- > dropEnd1 "test" == "tes"+-- > \xs -> dropEnd 1 xs == dropEnd1 xs+dropEnd1 :: [a] -> [a]+dropEnd1 [] = []+dropEnd1 (x:xs) = foldr (\z f y -> y : f z) (const []) xs x -- | Version on `concatMap` generalised to a `Monoid` rather than just a list.
src/Extra.hs view
@@ -23,7 +23,7 @@ writeIORef', atomicWriteIORef', atomicModifyIORef_, atomicModifyIORef'_, -- * Data.List.Extra -- | Extra functions available in @"Data.List.Extra"@.- lower, upper, trim, trimStart, trimEnd, word1, line1, escapeHTML, escapeJSON, unescapeHTML, unescapeJSON, dropEnd, takeEnd, splitAtEnd, breakEnd, spanEnd, dropWhileEnd', takeWhileEnd, stripSuffix, stripInfix, stripInfixEnd, dropPrefix, dropSuffix, wordsBy, linesBy, breakOn, breakOnEnd, splitOn, split, chunksOf, notNull, list, unsnoc, cons, snoc, drop1, mconcatMap, enumerate, groupSort, groupSortOn, groupSortBy, nubOrd, nubOrdBy, nubOrdOn, nubOn, groupOn, nubSort, nubSortBy, nubSortOn, maximumOn, minimumOn, disjoint, allSame, anySame, repeatedly, for, firstJust, concatUnzip, concatUnzip3, zipFrom, zipWithFrom, replace, merge, mergeBy,+ lower, upper, trim, trimStart, trimEnd, word1, line1, escapeHTML, escapeJSON, unescapeHTML, unescapeJSON, dropEnd, takeEnd, splitAtEnd, breakEnd, spanEnd, dropWhileEnd', takeWhileEnd, stripSuffix, stripInfix, stripInfixEnd, dropPrefix, dropSuffix, wordsBy, linesBy, breakOn, breakOnEnd, splitOn, split, chunksOf, headDef, lastDef, notNull, list, unsnoc, cons, snoc, drop1, dropEnd1, mconcatMap, enumerate, groupSort, groupSortOn, groupSortBy, nubOrd, nubOrdBy, nubOrdOn, nubOn, groupOn, nubSort, nubSortBy, nubSortOn, maximumOn, minimumOn, disjoint, allSame, anySame, repeatedly, for, firstJust, concatUnzip, concatUnzip3, zipFrom, zipWithFrom, replace, merge, mergeBy, -- * Data.List.NonEmpty.Extra -- | Extra functions available in @"Data.List.NonEmpty.Extra"@. (|:), (|>), appendl, appendr, maximum1, minimum1, maximumBy1, minimumBy1, maximumOn1, minimumOn1,
test/TestGen.hs view
@@ -21,6 +21,7 @@ testGen "ignore (print 1) == print 1" $ ignore (print 1) == print 1 testGen "ignore (fail \"die\") == return ()" $ ignore (fail "die") == return () testGen "catch (errorIO \"Hello\") (\\(ErrorCall x) -> return x) == return \"Hello\"" $ catch (errorIO "Hello") (\(ErrorCall x) -> return x) == return "Hello"+ testGen "seq (errorIO \"foo\") (print 1) == print 1" $ seq (errorIO "foo") (print 1) == print 1 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 ()@@ -88,6 +89,12 @@ testGen "allSame [] == True" $ allSame [] == True testGen "allSame (1:1:2:undefined) == False" $ allSame (1:1:2:undefined) == False testGen "\\xs -> allSame xs == (length (nub xs) <= 1)" $ \xs -> allSame xs == (length (nub xs) <= 1)+ testGen "headDef 1 [] == 1" $ headDef 1 [] == 1+ testGen "headDef 1 [2,3,4] == 2" $ headDef 1 [2,3,4] == 2+ testGen "\\x xs -> headDef x xs == fromMaybe x (listToMaybe xs)" $ \x xs -> headDef x xs == fromMaybe x (listToMaybe xs)+ testGen "lastDef 1 [] == 1" $ lastDef 1 [] == 1+ testGen "lastDef 1 [2,3,4] == 4" $ lastDef 1 [2,3,4] == 4+ testGen "\\x xs -> lastDef x xs == last (x:xs)" $ \x xs -> lastDef x xs == last (x:xs) testGen "notNull [] == False" $ notNull [] == False testGen "notNull [1] == True" $ notNull [1] == True testGen "\\xs -> notNull xs == not (null xs)" $ \xs -> notNull xs == not (null xs)@@ -182,6 +189,9 @@ testGen "drop1 \"\" == \"\"" $ drop1 "" == "" testGen "drop1 \"test\" == \"est\"" $ drop1 "test" == "est" testGen "\\xs -> drop 1 xs == drop1 xs" $ \xs -> drop 1 xs == drop1 xs+ testGen "dropEnd1 \"\" == \"\"" $ dropEnd1 "" == ""+ testGen "dropEnd1 \"test\" == \"tes\"" $ dropEnd1 "test" == "tes"+ testGen "\\xs -> dropEnd 1 xs == dropEnd1 xs" $ \xs -> dropEnd 1 xs == dropEnd1 xs testGen "mconcatMap Sum [1,2,3] == Sum 6" $ mconcatMap Sum [1,2,3] == Sum 6 testGen "\\f xs -> mconcatMap f xs == concatMap f xs" $ \f xs -> mconcatMap f xs == concatMap f xs testGen "breakOn \"::\" \"a::b::c\" == (\"a\", \"::b::c\")" $ breakOn "::" "a::b::c" == ("a", "::b::c")
test/TestUtil.hs view
@@ -24,6 +24,7 @@ import Data.IORef.Extra as X import Data.List.Extra as X hiding (union, unionBy) import Data.List.NonEmpty.Extra as X (NonEmpty(..), (|>), (|:), appendl, appendr, union, unionBy)+import Data.Maybe as X import Data.Monoid as X import Data.Tuple.Extra as X import Data.Typeable.Extra as X