diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cf53a8ee..1720c962 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,10 +1,13 @@ name: CI -# Trigger the workflow on push or pull request, but only for the main branch on: pull_request: + types: [synchronize, opened, reopened] push: branches: [main] + schedule: + # additionally run once per week (At 00:00 on Sunday) to maintain cache + - cron: '0 0 * * 0' jobs: cabal: @@ -46,7 +49,6 @@ jobs: steps: - uses: actions/checkout@v2 - if: github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.ref == 'refs/heads/main' - uses: haskell/actions/setup@v1 id: setup-haskell-cabal @@ -55,24 +57,35 @@ jobs: ghc-version: ${{ matrix.ghc }} cabal-version: ${{ matrix.cabal }} - - uses: actions/cache@v1 - name: Cache cabal-store + - name: Configure + run: | + cabal configure --enable-tests --enable-benchmarks --enable-documentation --test-show-details=direct --write-ghc-environment-files=always + + - name: Freeze + run: | + cabal freeze + + - uses: actions/cache@v2.1.3 + name: Cache ~/.cabal/store with: path: ${{ steps.setup-haskell-cabal.outputs.cabal-store }} - key: ${{ runner.os }}-${{ matrix.ghc }}-cabal + key: ${{ runner.os }}-${{ matrix.ghc }}-${{ hashFiles('cabal.project.freeze') }} + + - name: Install dependencies + run: | + cabal build all --only-dependencies - name: Build run: | - cabal update - cabal build --enable-tests --enable-benchmarks --write-ghc-environment-files=always + cabal build all - name: Test run: | - cabal test --enable-tests --test-show-details=direct + cabal test all - name: Documentation run: | - cabal haddock --enable-documentation + cabal haddock stack: name: stack / ghc ${{ matrix.ghc }} @@ -84,7 +97,6 @@ jobs: steps: - uses: actions/checkout@v2 - if: github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.ref == 'refs/heads/main' - uses: haskell/actions/setup@v1 name: Setup Haskell Stack @@ -98,6 +110,10 @@ jobs: path: ~/.stack key: ${{ runner.os }}-${{ matrix.ghc }}-stack + - name: Install dependencies + run: | + stack build --system-ghc --test --bench --no-run-tests --no-run-benchmarks --only-dependencies + - name: Build run: | stack build --system-ghc --test --bench --no-run-tests --no-run-benchmarks diff --git a/CHANGELOG.md b/CHANGELOG.md index cca0f25c..52d8c0c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ `relude` uses [PVP Versioning][1]. The changelog is available [on GitHub][2]. -## Unreleased: 0.8.0.0 +## 1.0.0.0 — Mar 12, 2021 * [#353](https://github.com/kowainik/relude/issues/353): Reexport most common modules from the following libraries: @@ -29,14 +29,9 @@ The changelog is available [on GitHub][2]. * [#345](https://github.com/kowainik/relude/issues/345): Support GHC-9.0. -* Upgrade to GHC-8.10.4, GHC-8.8.4. -* Add `infinitely` as more strictly typed `forever`. -* Remove `Eq` constraint on `universeNonEmpty` -* Add `maybeAt`, `!!?` with its arguments flipped. -* [#346](https://github.com/kowainik/relude/issues/346): - Reimplement `ordNub` through `nubOrd` from `containers`. - - Add `intNub` and `intNubOn` functions. +* Upgrade minor GHC versions to GHC-8.10.4 and GHC-8.8.4. +* [#268](https://github.com/kowainik/relude/issues/268): + Drop support of GHC-8.0.2. * [#270](https://github.com/kowainik/relude/issues/270): Standardise `universe`, `universeNonEmpty` and `inverseMap` functions that previously were introduced in the `Relude.Extra.Enum` module. `Relude.Enum` @@ -45,11 +40,67 @@ The changelog is available [on GitHub][2]. __Migration guide:__ If you were using any of these functions you can now remove `Relude.Extra.Enum` from your imports and explicit `mixins` section as they are available for you with the `Relude` module. -* [#347](https://github.com/kowainik/relude/issues/347): - Add `ordNubOn` function. -* [#268](https://github.com/kowainik/relude/issues/268): - Drop support of GHC-8.0.2. -* Add lifted `readFile'` function. +* Remove the `Eq` constraint on `universeNonEmpty` +* [#269](https://github.com/kowainik/relude/issues/269): + Remove the `Relude.Extra.Validation` module. + + __Migration guide:__ + If you use `Relude.Extra.Validation` in you project you need to: + + 1. Add `validation-selective` into the `build-depends` section of your + `.cabal` file. + 2. Change imports of `Relude.Extra.Validation` to `Validation`: + + ```haskell + -- Was: + import Relude.Extra.Validation (Validation (..), ..) + -- Became: + import Validation (Validation (..), ..) + ``` + +* [#346](https://github.com/kowainik/relude/issues/346), + [#347](https://github.com/kowainik/relude/issues/347): + Reimplement `ordNub` through `nubOrd` from `containers`. + Add `ordNubOn`, `intNub` and `intNubOn` functions. +* [#327](https://github.com/kowainik/relude/issues/327): + Add `infinitely` as more strictly typed `forever`. +* [#311](https://github.com/kowainik/relude/issues/311): + Add `maybeAt` function — the non-operator version of `!!?` with its + arguments flipped. +* [#314](https://github.com/kowainik/relude/issues/314): + Add lifted versions of functions to work with `Handle`: + + + `hFlush` + + `hIsEOF` + + `hSetBuffering` + + `hGetBuffering` +* [#305](https://github.com/kowainik/relude/issues/305): + Add lifted versions of functions to work with environment: + + + `getArgs` + + `lookupEnv` +* Add lifted version of the `readFile'` function. +* Reexport the `BufferMode` type from `base`. +* [#309](https://github.com/kowainik/relude/issues/309): + Reexport `span` from `Data.List`. +* [#319](https://github.com/kowainik/relude/issues/319): + Implement `partitionWith`. +* [#307](https://github.com/kowainik/relude/issues/307): + Add `foldr1` to `Foldable1`. +* [#316](https://github.com/kowainik/relude/issues/316): + Add `average` and `average1` — efficient functions for finding + average on foldable structures. +* [#306](https://github.com/kowainik/relude/issues/306): + Add `maximumOn1` and `minimumOn1` to `Foldable1`. +* [#301](https://github.com/kowainik/relude/issues/301): + Add `traceShowWith` to `Relude.Debug`. +* [#304](https://github.com/kowainik/relude/issues/304), + [#317](https://github.com/kowainik/relude/issues/317): + Various documentation improvements. +* Updates to `relude`-specific `.hlint` rules. + +Thanks @googleson78, @sushi-shi, @rektrex, @aleator, @mjgpy3, @dalpd, +@Bodigrim for helping with this release! ## 0.7.0.0 — May 14, 2020 diff --git a/README.md b/README.md index c14b0bd6..fc7a0717 100644 --- a/README.md +++ b/README.md @@ -227,7 +227,7 @@ version: 0.0.0.0 library exposed-modules: Example build-depends: base >= 4.10 && < 4.13 - , relude ^>= x.x.x.x + , relude ^>= 1.0.0.0 mixins: base hiding (Prelude) , relude (Relude as Prelude) @@ -681,7 +681,7 @@ For the latest `relude` version, this can be achieved by executing the following two commands on your CI: ```yaml -curl https://raw.githubusercontent.com/kowainik/relude/v0.7.0.0/.hlint.yaml -o .hlint-relude.yaml +curl https://raw.githubusercontent.com/kowainik/relude/v1.0.0.0/.hlint.yaml -o .hlint-relude.yaml curl -sSL https://raw.github.com/ndmitchell/neil/master/misc/travis.sh | sh -s -- hlint -h .hlint-relude.yaml . ``` diff --git a/relude.cabal b/relude.cabal index cdf72065..99b487e4 100644 --- a/relude.cabal +++ b/relude.cabal @@ -1,6 +1,6 @@ cabal-version: 3.0 name: relude -version: 0.7.0.0 +version: 1.0.0.0 synopsis: Safe, performant, user-friendly and lightweight Haskell Standard Library description: @__relude__@ is an alternative prelude library. If you find the default diff --git a/src/Relude/Debug.hs b/src/Relude/Debug.hs index b52b6697..4b3636ce 100644 --- a/src/Relude/Debug.hs +++ b/src/Relude/Debug.hs @@ -180,6 +180,8 @@ instance: 1 * If you don't need such flexibility, use simpler 'trace', 'traceShow' or 'traceShowId' + +@since 1.0.0.0 -} traceShowWith :: Show b => (a -> b) -> a -> a traceShowWith f v = Debug.traceShow (f v) v @@ -252,13 +254,13 @@ error handling mechanism. >>> error "oops" *** Exception: oops CallStack (from HasCallStack): - error, called at src\\Relude\\Debug.hs:286:11 in ... + error, called at src\\Relude\\Debug.hs:288:11 in ... ... #else >>> error "oops" *** Exception: oops CallStack (from HasCallStack): - error, called at src/Relude/Debug.hs:286:11 in ... + error, called at src/Relude/Debug.hs:288:11 in ... ... #endif diff --git a/src/Relude/Enum.hs b/src/Relude/Enum.hs index 7df22f46..f0d97ec3 100644 --- a/src/Relude/Enum.hs +++ b/src/Relude/Enum.hs @@ -13,7 +13,7 @@ extra modules, but due to their benefit in different use cases. If you imported @Relude.Extra.Enum@ module, you can remove it now, as these functions are reexported in the main "Relude" module. -@since x.x.x.x +@since 1.0.0.0 -} module Relude.Enum diff --git a/src/Relude/Extra/Foldable.hs b/src/Relude/Extra/Foldable.hs index c438c3d8..1bbcdfb3 100644 --- a/src/Relude/Extra/Foldable.hs +++ b/src/Relude/Extra/Foldable.hs @@ -55,7 +55,7 @@ Just 2.75 >>> average [] Nothing -@since 0.8.0.0 +@since 1.0.0.0 -} average :: forall a f . (Foldable f, Fractional a) => f a -> Maybe a average xs diff --git a/src/Relude/Extra/Foldable1.hs b/src/Relude/Extra/Foldable1.hs index 3aaf9f2e..dfe06feb 100644 --- a/src/Relude/Extra/Foldable1.hs +++ b/src/Relude/Extra/Foldable1.hs @@ -1,11 +1,11 @@ {-# OPTIONS_GHC -Wno-redundant-constraints #-} +{-# LANGUAGE BangPatterns #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE Safe #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} -{-# LANGUAGE BangPatterns #-} {- | Copyright: (c) 2011-2015 Edward Kmett @@ -31,7 +31,7 @@ module Relude.Extra.Foldable1 ) where import Relude hiding (Product (..), Sum (..)) -import Relude.Extra.Newtype (( #. )) +import Relude.Extra.Newtype ((#.)) import Data.Functor.Product (Product (..)) import Data.Functor.Sum (Sum (..)) @@ -75,6 +75,8 @@ class Foldable f => Foldable1 f where 6 >>> foldr1 (+) 1 $ Identity 3 4 + + @since 1.0.0.0 -} foldr1 :: (a -> b -> b) -> b -> f a -> b foldr1 f accum as = appEndo (foldMap1 (Endo #. f) as) accum @@ -125,6 +127,8 @@ class Foldable f => Foldable1 f where >>> maximumOn1 abs (0 :| [2, 1, -3, -2]) -3 + + @since 1.0.0.0 -} maximumOn1 :: Ord b => (a -> b) -> f a -> a maximumOn1 f = maximumOn1 f . toNonEmpty @@ -135,6 +139,8 @@ class Foldable f => Foldable1 f where >>> minimumOn1 abs (0 :| [2, 1, -3, -2]) 0 + + @since 1.0.0.0 -} minimumOn1 :: Ord b => (a -> b) -> f a -> a minimumOn1 f = minimumOn1 f . toNonEmpty @@ -178,7 +184,7 @@ instance Foldable1 NonEmpty where cmpOn :: a -> a -> a cmpOn a b = case func a `compare` func b of GT -> a - _ -> b + _ -> b {-# INLINE maximumOn1 #-} minimumOn1 :: forall a b. Ord b => (a -> b) -> NonEmpty a -> a @@ -187,7 +193,7 @@ instance Foldable1 NonEmpty where cmpOn :: a -> a -> a cmpOn a b = case func a `compare` func b of LT -> a - _ -> b + _ -> b {-# INLINE minimumOn1 #-} {- | @@ -396,7 +402,7 @@ possible and returns the resulting element. >>> average1 (1 :| [2,3,4]) 2.5 -@since 0.8.0.0 +@since 1.0.0.0 -} average1 :: forall a f . (Foldable1 f, Fractional a) => f a -> a average1 = uncurry (/) . foldl' (\(!total, !count) x -> (total + x, count + 1)) (0,0) diff --git a/src/Relude/Lifted/Env.hs b/src/Relude/Lifted/Env.hs index a38a77e1..306e7e5b 100644 --- a/src/Relude/Lifted/Env.hs +++ b/src/Relude/Lifted/Env.hs @@ -7,7 +7,7 @@ Portability: Portable Lifted functions to work with system environment. -@since 0.8.0.0 +@since 1.0.0.0 -} module Relude.Lifted.Env @@ -24,7 +24,7 @@ import qualified System.Environment as ENV (getArgs, lookupEnv) {- | Lifted version of 'System.Environment.getArgs'. -@since 0.8.0.0 +@since 1.0.0.0 -} getArgs :: MonadIO m => m [String] getArgs = liftIO ENV.getArgs @@ -33,7 +33,7 @@ getArgs = liftIO ENV.getArgs {- | Lifted version of 'System.Environment.lookupEnv'. -@since 0.8.0.0 +@since 1.0.0.0 -} lookupEnv :: MonadIO m => String -> m (Maybe String) lookupEnv = liftIO . ENV.lookupEnv diff --git a/src/Relude/Lifted/File.hs b/src/Relude/Lifted/File.hs index 292259cd..daf44aae 100644 --- a/src/Relude/Lifted/File.hs +++ b/src/Relude/Lifted/File.hs @@ -39,7 +39,7 @@ readFile = liftIO . IO.readFile #if ( __GLASGOW_HASKELL__ >= 900 ) {- | Lifted version of 'IO.readFile''. Strict version of 'readFile'. -@since x.x.x.x +@since 1.0.0.0 -} readFile' :: MonadIO m => FilePath -> m String readFile' = liftIO . IO.readFile' diff --git a/src/Relude/Lifted/Handle.hs b/src/Relude/Lifted/Handle.hs index 2f5c4778..21bd2f2c 100644 --- a/src/Relude/Lifted/Handle.hs +++ b/src/Relude/Lifted/Handle.hs @@ -7,7 +7,7 @@ Portability: Portable Lifted functions to work with 'IO' 'Handle's. -@since 0.8.0.0 +@since 1.0.0.0 -} module Relude.Lifted.Handle @@ -32,7 +32,7 @@ import System.IO (Handle, stdin, stdout, stderr, withFile, BufferMode (..)) {- | Lifted version of 'IO.hFlush'. -@since 0.8.0.0 +@since 1.0.0.0 -} hFlush :: MonadIO m => IO.Handle -> m () hFlush = liftIO . IO.hFlush @@ -41,7 +41,7 @@ hFlush = liftIO . IO.hFlush {- | Lifted version of 'IO.hIsEOF'. -@since 0.8.0.0 +@since 1.0.0.0 -} hIsEOF :: MonadIO m => IO.Handle -> m Bool hIsEOF = liftIO . IO.hIsEOF @@ -50,7 +50,7 @@ hIsEOF = liftIO . IO.hIsEOF {- | Lifted version of 'IO.hSetBuffering'. -@since 0.8.0.0 +@since 1.0.0.0 -} hSetBuffering :: MonadIO m => IO.Handle -> IO.BufferMode -> m () hSetBuffering h = liftIO . IO.hSetBuffering h @@ -59,7 +59,7 @@ hSetBuffering h = liftIO . IO.hSetBuffering h {- | Lifted version of 'IO.hGetBuffering'. -@since 0.8.0.0 +@since 1.0.0.0 -} hGetBuffering :: MonadIO m => IO.Handle -> m IO.BufferMode hGetBuffering = liftIO . IO.hGetBuffering diff --git a/src/Relude/List.hs b/src/Relude/List.hs index 4e89b9e4..5ab54d93 100644 --- a/src/Relude/List.hs +++ b/src/Relude/List.hs @@ -81,6 +81,7 @@ Nothing >>> maybeAt 2 ["a", "b", "c"] Just "c" +@since 1.0.0.0 -} maybeAt :: Int -> [a] -> Maybe a maybeAt = flip (!!?) @@ -101,7 +102,7 @@ are extracted to the second element of output. >>> partitionWith divideEvenOrShow [1 .. 6] ([1,2,3],["Odd: 1","Odd: 3","Odd: 5"]) -@since 0.8.0.0 +@since 1.0.0.0 -} partitionWith :: (a -> Either b c) -> [a] -> ([b], [c]) partitionWith f = partitionEithers . map f diff --git a/src/Relude/Monad.hs b/src/Relude/Monad.hs index 910ff0b0..e7e8666c 100644 --- a/src/Relude/Monad.hs +++ b/src/Relude/Monad.hs @@ -69,7 +69,7 @@ getIntForever = do In contrast, using 'infinitely' instead of 'forever' in 'foo' is a type error. -@since 0.8.0.0 +@since 1.0.0.0 -} infinitely :: Applicative f => f a -> f Void infinitely = forever diff --git a/src/Relude/Nub.hs b/src/Relude/Nub.hs index 5e20c7f3..1ca2800b 100644 --- a/src/Relude/Nub.hs +++ b/src/Relude/Nub.hs @@ -99,7 +99,7 @@ function. >>> ordNubOn (`div` 10) [3, 3, 3, 13, 2, 22, -1, 1, 66] [3,13,22,-1,66] -@since x.x.x.x +@since 1.0.0.0 -} ordNubOn :: forall b a . (Ord b) => (a -> b) -> [a] -> [a] ordNubOn = Containers.nubOrdOn @@ -154,7 +154,7 @@ Like 'Prelude.nub' but runs in \( O(n \min\(n, int_bits\)) \) time and requires >>> intNub [3, 3, 3, 2, 2, -1, 1] [3,2,-1,1] -@since x.x.x.x +@since 1.0.0.0 -} intNub :: [Int] -> [Int] intNub = Containers.nubInt @@ -166,7 +166,7 @@ intNub = Containers.nubInt >>> intNubOn fromEnum "ababbbcdaffee" "abcdfe" -@since x.x.x.x +@since 1.0.0.0 -} intNubOn :: (a -> Int) -> [a] -> [a] intNubOn = Containers.nubIntOn