extra 1.7.1 → 1.7.2
raw patch · 12 files changed
+54/−37 lines, 12 filesdep −semigroupsdep ~basePVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies removed: semigroups
Dependency ranges changed: base
API changes (from Hackage documentation)
+ Data.List.Extra: zipWithLongest :: (Maybe a -> Maybe b -> c) -> [a] -> [b] -> [c]
+ Extra: zipWithLongest :: (Maybe a -> Maybe b -> c) -> [a] -> [b] -> [c]
- Extra: duration :: IO a -> IO (Seconds, a)
+ Extra: duration :: MonadIO m => m a -> m (Seconds, a)
- System.Time.Extra: duration :: IO a -> IO (Seconds, a)
+ System.Time.Extra: duration :: MonadIO m => m a -> m (Seconds, a)
Files
- CHANGES.txt +6/−0
- extra.cabal +3/−5
- src/Control/Concurrent/Extra.hs +7/−19
- src/Data/List/Extra.hs +15/−1
- src/Data/Typeable/Extra.hs +1/−1
- src/Extra.hs +1/−1
- src/System/Environment/Extra.hs +2/−3
- src/System/Time/Extra.hs +4/−3
- src/Text/Read/Extra.hs +1/−1
- test/TestCustom.hs +11/−2
- test/TestGen.hs +3/−0
- test/TestUtil.hs +0/−1
CHANGES.txt view
@@ -1,5 +1,11 @@ Changelog for Extra +1.7.2, released 2020-05-25+ #56, add zipWithLongest+ #57, make duration in MonadIO+ Simplify and optimise Barrier+ Mark modules that are empty as DEPRECATED+ Remove support for GHC 7.10 1.7.1, released 2020-03-10 Add NOINLINE to errorIO to work around a GHC 8.4 bug 1.7, released 2020-03-05
extra.cabal view
@@ -1,7 +1,7 @@ cabal-version: >= 1.18 build-type: Simple name: extra-version: 1.7.1+version: 1.7.2 license: BSD3 license-file: LICENSE category: Development@@ -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.8.1, GHC==8.6.5, GHC==8.4.4, GHC==8.2.2, GHC==8.0.2, GHC==7.10.3+tested-with: GHC==8.10.1, GHC==8.8.3, GHC==8.6.5, GHC==8.4.4, GHC==8.2.2, GHC==8.0.2 extra-doc-files: CHANGES.txt@@ -31,13 +31,11 @@ default-language: Haskell2010 hs-source-dirs: src build-depends:- base >= 4.8 && < 5,+ base >= 4.9 && < 5, directory, filepath, process, clock >= 0.7,- -- For GHC 7.10 since Data.List.NonEmpty wasn't in base then- semigroups, time if !os(windows) build-depends: unix
src/Control/Concurrent/Extra.hs view
@@ -182,38 +182,26 @@ -- for it to complete. A barrier has similarities to a future or promise -- from other languages, has been known as an IVar in other Haskell work, -- and in some ways is like a manually managed thunk.-newtype Barrier a = Barrier (Var (Either (MVar ()) a))- -- Either a Left empty MVar you should wait or a Right result- -- With base 4.7 and above readMVar is atomic so you probably can implement Barrier directly on MVar a+newtype Barrier a = Barrier (MVar a) -- | Create a new 'Barrier'. newBarrier :: IO (Barrier a)-newBarrier = fmap Barrier $ newVar . Left =<< newEmptyMVar+newBarrier = Barrier <$> newEmptyMVar -- | Write a value into the Barrier, releasing anyone at 'waitBarrier'. -- Any subsequent attempts to signal the 'Barrier' will throw an exception. signalBarrier :: Partial => Barrier a -> a -> IO ()-signalBarrier (Barrier var) v = mask_ $ -- use mask so never in an inconsistent state- join $ modifyVar var $ \x -> case x of- Left bar -> pure (Right v, putMVar bar ())- Right res -> error "Control.Concurrent.Extra.signalBarrier, attempt to signal a barrier that has already been signaled"+signalBarrier (Barrier var) v = do+ b <- tryPutMVar var v+ unless b $ errorIO "Control.Concurrent.Extra.signalBarrier, attempt to signal a barrier that has already been signaled" -- | Wait until a barrier has been signaled with 'signalBarrier'. waitBarrier :: Barrier a -> IO a-waitBarrier (Barrier var) = do- x <- readVar var- case x of- Right res -> pure res- Left bar -> do- readMVar bar- x <- readVar var- case x of- Right res -> pure res- Left bar -> error "Control.Concurrent.Extra, internal invariant violated in Barrier"+waitBarrier (Barrier var) = readMVar var -- | A version of 'waitBarrier' that never blocks, returning 'Nothing' -- if the barrier has not yet been signaled. waitBarrierMaybe :: Barrier a -> IO (Maybe a)-waitBarrierMaybe (Barrier bar) = eitherToMaybe <$> readVar bar+waitBarrierMaybe (Barrier bar) = tryReadMVar bar
src/Data/List/Extra.hs view
@@ -31,7 +31,7 @@ disjoint, allSame, anySame, repeatedly, firstJust, concatUnzip, concatUnzip3,- zipFrom, zipWithFrom,+ zipFrom, zipWithFrom, zipWithLongest, replace, merge, mergeBy, ) where @@ -769,3 +769,17 @@ balance a x (T R b y (T R c z d)) = T R (T B a x b) y (T B c z d) balance a x (T R (T R b y c) z d) = T R (T B a x b) y (T B c z d) balance a x b = T B a x b+++-- | Like 'zipWith', but keep going to the longest value. The function+-- argument will always be given at least one 'Just', and while both+-- lists have items, two 'Just' values.+--+-- > zipWithLongest (,) "a" "xyz" == [(Just 'a', Just 'x'), (Nothing, Just 'y'), (Nothing, Just 'z')]+-- > zipWithLongest (,) "a" "x" == [(Just 'a', Just 'x')]+-- > zipWithLongest (,) "" "x" == [(Nothing, Just 'x')]+zipWithLongest :: (Maybe a -> Maybe b -> c) -> [a] -> [b] -> [c]+zipWithLongest f [] [] = []+zipWithLongest f (x:xs) (y:ys) = f (Just x) (Just y) : zipWithLongest f xs ys+zipWithLongest f [] ys = map (f Nothing . Just) ys+zipWithLongest f xs [] = map ((`f` Nothing) . Just) xs
src/Data/Typeable/Extra.hs view
@@ -3,7 +3,7 @@ -- The package also exports the existing "Data.Typeable" functions. -- -- Currently this module has no functionality beyond "Data.Typeable".-module Data.Typeable.Extra(+module Data.Typeable.Extra {-# DEPRECATED "Use Data.Typeable directly" #-} ( module Data.Typeable ) where
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, 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, 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, firstJust, concatUnzip, concatUnzip3, zipFrom, zipWithFrom, zipWithLongest, replace, merge, mergeBy, -- * Data.List.NonEmpty.Extra -- | Extra functions available in @"Data.List.NonEmpty.Extra"@. (|:), (|>), appendl, appendr, maximum1, minimum1, maximumBy1, minimumBy1, maximumOn1, minimumOn1,
src/System/Environment/Extra.hs view
@@ -1,9 +1,8 @@ --- | Extra functions for "System.Environment". All these functions are available in later GHC versions,--- but this code works all the way back to GHC 7.2.+-- | Extra functions for "System.Environment". -- -- Currently this module has no functionality beyond "System.Environment".-module System.Environment.Extra(+module System.Environment.Extra {-# DEPRECATED "Use System.Environment directly" #-} ( module System.Environment, ) where
src/System/Time/Extra.hs view
@@ -15,6 +15,7 @@ import Control.Concurrent import System.Clock import Numeric.Extra+import Control.Monad.IO.Class import Control.Monad.Extra import Control.Exception.Extra import Data.Typeable@@ -108,9 +109,9 @@ -- | Record how long a computation takes in 'Seconds'. -- -- > do (a,_) <- duration $ sleep 1; pure $ a >= 1 && a <= 1.5-duration :: IO a -> IO (Seconds, a)+duration :: MonadIO m => m a -> m (Seconds, a) duration act = do- time <- offsetTime+ time <- liftIO offsetTime res <- act- time <- time+ time <- liftIO time pure (time, res)
src/Text/Read/Extra.hs view
@@ -2,7 +2,7 @@ -- | This module provides "Text.Read" with functions added in later versions. -- -- Currently this module has no functionality beyond "Text.Read".-module Text.Read.Extra(+module Text.Read.Extra {-# DEPRECATED "Use Text.Read directly" #-} ( module Text.Read, ) where
test/TestCustom.hs view
@@ -6,13 +6,13 @@ import System.IO.Extra import Data.IORef import TestUtil-import Data.Typeable.Extra as X+import Data.List.Extra as X testCustom :: IO () testCustom = do -- check that Extra really does export these things- testGen "Extra export" $ Proxy == (X.Proxy :: Proxy ())+ testGen "Extra export" $ X.sort [1] == [1] testRaw "withTempFile" $ do xs <- replicateM 4 $ onceFork $ do@@ -32,3 +32,12 @@ ref <- newIORef 2 retry 5 $ do modifyIORef ref pred; whenM ((/=) 0 <$> readIORef ref) $ fail "die" (==== 0) <$> readIORef ref++ testRaw "barrier" $ do+ bar <- newBarrier+ (==== Nothing) <$> waitBarrierMaybe bar+ signalBarrier bar 1+ (==== Just 1) <$> waitBarrierMaybe bar+ (==== 1) <$> waitBarrier bar+ Left _ <- try_ $ signalBarrier bar 2+ pure ()
test/TestGen.hs view
@@ -241,6 +241,9 @@ testGen "\\xs -> nubOrd xs == nub xs" $ \xs -> nubOrd xs == nub xs testGen "nubOrdOn length [\"a\",\"test\",\"of\",\"this\"] == [\"a\",\"test\",\"of\"]" $ nubOrdOn length ["a","test","of","this"] == ["a","test","of"] testGen "nubOrdBy (compare `on` length) [\"a\",\"test\",\"of\",\"this\"] == [\"a\",\"test\",\"of\"]" $ nubOrdBy (compare `on` length) ["a","test","of","this"] == ["a","test","of"]+ testGen "zipWithLongest (,) \"a\" \"xyz\" == [(Just 'a', Just 'x'), (Nothing, Just 'y'), (Nothing, Just 'z')]" $ zipWithLongest (,) "a" "xyz" == [(Just 'a', Just 'x'), (Nothing, Just 'y'), (Nothing, Just 'z')]+ testGen "zipWithLongest (,) \"a\" \"x\" == [(Just 'a', Just 'x')]" $ zipWithLongest (,) "a" "x" == [(Just 'a', Just 'x')]+ testGen "zipWithLongest (,) \"\" \"x\" == [(Nothing, Just 'x')]" $ zipWithLongest (,) "" "x" == [(Nothing, Just 'x')] testGen "(1 :| [2,3]) |> 4 |> 5 == 1 :| [2,3,4,5]" $ (1 :| [2,3]) |> 4 |> 5 == 1 :| [2,3,4,5] testGen "[1,2,3] |: 4 |> 5 == 1 :| [2,3,4,5]" $ [1,2,3] |: 4 |> 5 == 1 :| [2,3,4,5] testGen "appendl (1 :| [2,3]) [4,5] == 1 :| [2,3,4,5]" $ appendl (1 :| [2,3]) [4,5] == 1 :| [2,3,4,5]
test/TestUtil.hs view
@@ -27,7 +27,6 @@ import Data.Maybe as X import Data.Monoid as X import Data.Tuple.Extra as X-import Data.Typeable.Extra as X import Data.Version.Extra as X import Numeric.Extra as X import System.Directory.Extra as X