relude 0.3.0 → 0.4.0
raw patch · 15 files changed
+456/−77 lines, 15 filesdep −utf8-string
Dependencies removed: utf8-string
Files
- CHANGELOG.md +35/−0
- CONTRIBUTING.md +36/−36
- README.md +18/−6
- relude.cabal +7/−5
- src/Relude.hs +5/−0
- src/Relude/Bool/Guard.hs +21/−2
- src/Relude/Extra/Tuple.hs +62/−0
- src/Relude/Extra/Type.hs +45/−0
- src/Relude/Extra/Validation.hs +182/−0
- src/Relude/Foldable/Fold.hs +11/−2
- src/Relude/Foldable/Reexport.hs +13/−0
- src/Relude/Functor/Reexport.hs +10/−0
- src/Relude/Lifted/File.hs +1/−15
- src/Relude/Nub.hs +4/−4
- src/Relude/String/Conversion.hs +6/−7
CHANGELOG.md view
@@ -1,5 +1,40 @@ # Change log +Unreleased+====++0.4.0 — Nov 6, 2018+=====++* [#70](https://github.com/kowainik/relude/issues/70):+ Reexport `Contravariant` for GHC >= 8.6.1.+* [#103](https://github.com/kowainik/relude/pull/104):+ Drop `utf8-string` dependency and improve performance of conversion functions.+* [#98](https://github.com/kowainik/relude/issues/98):+ Reexport `Bifoldable` related stuff from `base`.+* [#99](https://github.com/kowainik/relude/issues/99):+ Reexport `Bitraversable` related stuff from `base`.+* [#100](https://github.com/kowainik/relude/issues/100):+ Add `Relude.Extra.Validation` with `Validation`data type.+* [#89](https://github.com/kowainik/relude/issues/81):+ Add `Relude.Extra.Type` module containing a `typeName` function.+* [#92](https://github.com/kowainik/relude/issues/92)+ Add `Relude.Extra.Tuple` module, containing+ `dupe`, `mapToFst`, `mapToSnd`, and `mapBoth` functions.+* [#97](https://github.com/kowainik/relude/issues/97):+ Add `(&&^)` and `(||^)` operators.+* [#81](https://github.com/kowainik/relude/issues/81):+ Add `asumMap` to `Foldable` functions.+* [#80](https://github.com/kowainik/relude/issues/80):+ Add hlint rules for `whenLeft`, `whenLeftM`, `whenRight` and `whenRightM`.+* [#79](https://github.com/kowainik/relude/issues/79):+ Add HLint rules for `One` typeclass.+* Remove `openFile` and `hClose`.+* [#83](https://github.com/kowainik/relude/pull/83):+ Make documentation for `nub` functions prettier.+* [#109](https://github.com/kowainik/relude/issues/109):+ Use Dhall v3.0.0 for hlint file generation.+ 0.3.0 =====
CONTRIBUTING.md view
@@ -1,53 +1,53 @@-# Contributing to `relude`+# Contributing to the Kowainik repositories ## :wave: Greetings Traveler! -We're glad you're reading this, we really appreciate the effort you're-putting in. Thank you for your help in making this library awesome! :sparkles:+We are delighted you're reading this, and we appreciate the effort you're+taking to make our projects awesome! :sparkles: -### How to contribute+## How to contribute -#### Report bugs or feature request+### :bug: Report bugs or feature request :bulb: -If you have found any bugs or have proposals on how to make this project better,-don't hesitate to create issues-[here](https://github.com/kowainik/relude/issues/new) in free format.+If you discover a bug or have any proposals on how to make this project better+don't hesitate to create an issue [here](../../issues/new) in a free format. -#### Create a PR+### Create a PR -We love receiving pull requests from everyone. But, please, don't create a PR-without a corresponding issue. It's always better to discuss your future-work first. Even if such an issue exists it's still better to express your willing-to do that issue under comment section. Thus you will show that you're doing-that issue, and nobody else will accidentally do it in parallel with you. Furthermore,-you also can discuss the best way to implement that issue!+We love to receive pull requests from everyone! It's usually a good idea+to tell about your intention to work on something under the corresponding+issue, so everyone is aware that you're on it. If there's no such issue — simply+create a new one! -To get started with this you should first fork, then clone the repo:+To get started with the Pull Request implementation you should first +[fork](../../fork), then clone the repo: - git clone git@github.com:your-username/relude.git+ git clone git@github.com:your-username/project-name.git -Make your changes and consider the following check list to go through before submitting your pull request.+Make your changes and consider the following checklist to go through +before submitting your pull request. -#### :white_check_mark: Check list+### :white_check_mark: Check list+- [ ] New/fixed features work as expected (Bonus points for the new tests).+- [ ] There are no warnings during compilation.+- [ ] `hlint .` output is: _No Hints_ (see [`hlint`][hlint] tool docs).+- [ ] The code is formatted with the [`stylish-haskell`][stylish-tool] tool + using [stylish-haskell.yaml][stylish] file in the repository.+- [ ] The code style of the files you changed is preserved (for more specific + details on our style guide check [this document][style-guide]).+- [ ] Commit messages are in the proper format.+ Start the first line of the commit with the issue number in square parentheses.+ + **_Example:_** `[#42] Upgrade upper bounds of 'base'` -- [ ] Project compiles-- [ ] New/fixed features work as expected-- [ ] Old features do not break after the change-- [ ] All new and existing tests pass-- [ ] [`stylish-haskell`](https://github.com/kowainik/org/blob/master/.stylish-haskell.yaml)- with config in this repo root was used to format code-- [ ] _Recommended:_ Commit messages are in the proper format. If the commit- addresses an issue start the first line of the commit with the issue number in- square parentheses.- + **_Example:_** `[#42] Short commit description`-- [ ] All changes are reflected in `.hlint.yaml` (Use `hlint/hlint.dhall` to make changes).+After all above is done commit and push to your fork.+Now you are ready to [submit a pull request](../../compare). -If you fix bugs or add new features, please add tests. -After everything above is done, commit and push to your fork.-Now you are ready to [submit a pull request][pr]!- -----------Thanks for spending time on reading this contributing guide! :sparkling_heart:+Thanks for spending your time on reading this contributing guide! :sparkling_heart: -[pr]: https://github.com/kowainik/relude/compare/+[stylish]: .stylish-haskell.yaml+[stylish-tool]: http://hackage.haskell.org/package/stylish-haskell+[hlint]: http://hackage.haskell.org/package/hlint+[style-guide]: https://github.com/kowainik/org/blob/master/style-guide.md#haskell-style-guide
README.md view
@@ -33,7 +33,7 @@ 4. **Minimalism** (low number of dependencies). We don't force users of `relude` to stick to some specific lens or text formatting or logging library. 5. **Convenience** (like lifted to `MonadIO` functions, more reexports). But we- want to bring common types and functions (like `containers` and `bytestrng`)+ want to bring common types and functions (like `containers` and `bytestring`) into scope because they are used in almost every application anyways. 6. **Provide excellent documentation.** * Tutorial@@ -61,6 +61,7 @@ 3. [Reexports.](#reexports-) 4. [What's new?](#whats-new-) 6. [Migration guide.](#migration-guide-)+7. [For developers.](#for-developers-) This is neither a tutorial on _Haskell_ nor tutorial on each function contained in `Relude`. For detailed documentation of every function together with examples@@ -78,7 +79,8 @@ 1. Replace `base` dependency with corresponding version of `base-noprelude` in your `.cabal` file.-2. Add the following `Prelude` module to your project (both to filesystem and to `exposed-modules`):+2. Add a `relude` dependency to your `.cabal` file.+3. Add the following `Prelude` module to your project (both to filesystem and to `exposed-modules`): ```haskell module Prelude ( module Relude@@ -88,7 +90,7 @@ ``` > **NOTE:** if you use [`summoner`](https://github.com/kowainik/summoner) to generate Haskell project, > this tool can automatically create such structure for you when you specify custom prelude.-3. Optionally modify your `Prelude` to include more or less functions. Probably+4. Optionally modify your `Prelude` to include more or less functions. Probably you want to hide something from `Relude` module. Or maybe you want to add something from `Relude.Extra.*` modules! @@ -291,6 +293,8 @@ * `Foldable1` typeclass that contains generalized interface for folding non-empty structures like `NonEmpty`.+* `Validation` data type as an alternative to `Either` when you want to combine+ all errors. Explore `Extra` modules: [`Relude.Extra`](src/Relude/Extra/) @@ -337,9 +341,9 @@ + Use `(putStr[Ln]|readFile|writeFile|appendFile)[Text|LText|BS|LBS]` functions. 6. Run `hlint` using `.hlint.yaml` file from `relude` package to cleanup code and imports. -### For Developers+## For Developers [↑](#structure-of-this-tutorial) -#### Generating .hlint.yaml+### Generating .hlint.yaml Note, that we are using custom `hlint` setting which are `Relude` specific. To keep it up to date don't forget to reflect your changes in this file. We are@@ -351,6 +355,9 @@ $ cabal new-install dhall-json ``` +Dhall 3.0.0 is required, so make sure that the previous command installed+dhall-json >= 1.2.4.+ To generate `hlint` file: ```shell@@ -363,6 +370,11 @@ $ hlint test/Spec.hs ``` -### Acknowledgement+See our blog post where we describe the details of the implementation for this solution:++* [Dhall To HLint](https://kowainik.github.io/posts/2018-09-09-dhall-to-hlint)+++## Acknowledgement Icons made by [Freepik](http://www.freepik.com) from [www.flaticon.com](https://www.flaticon.com/) is licensed by [CC 3.0 BY](http://creativecommons.org/licenses/by/3.0/).
relude.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.0 name: relude-version: 0.3.0+version: 0.4.0 synopsis: Custom prelude from Kowainik description: == Goals@@ -57,6 +57,7 @@ tested-with: GHC == 8.0.2 , GHC == 8.2.2 , GHC == 8.4.3+ , GHC == 8.6.1 extra-doc-files: CHANGELOG.md , CONTRIBUTING.md , README.md@@ -110,13 +111,16 @@ Relude.String.Reexport -- not exported by default- Relude.Extra.Bifunctor+ Relude.Extra.Bifunctor Relude.Extra.CallStack Relude.Extra.Enum Relude.Extra.Foldable1 Relude.Extra.Group Relude.Extra.Map Relude.Extra.Newtype+ Relude.Extra.Tuple+ Relude.Extra.Type+ Relude.Extra.Validation Relude.Unsafe ghc-options: -Wall@@ -133,11 +137,10 @@ , ghc-prim >= 0.4.0.0 && < 0.6 , hashable ^>= 1.2 , mtl ^>= 2.2- , stm ^>= 2.4+ , stm >= 2.4 && < 2.6 , text ^>= 1.2 , transformers ^>= 0.5 , unordered-containers >= 0.2.7 && < 0.3- , utf8-string ^>= 1.0 default-language: Haskell2010 default-extensions: NoImplicitPrelude@@ -154,7 +157,6 @@ , relude , bytestring , text- , utf8-string , hedgehog >= 0.6 , tasty , tasty-hedgehog
src/Relude.hs view
@@ -83,10 +83,15 @@ 'CallStack'. * __"Relude.Extra.Enum"__: extra utilities for types that implement 'Bounded' and 'Enum' constraints.+* __"Relude.Extra.Foldable1"__: 'Foldable1' typeclass like 'Foldable' but for+ non-empty structures. * __"Relude.Extra.Group"__: grouping functions, polymorphic on return @Map@ type. * __"Relude.Extra.Map"__: typeclass for @Map@-like data structures. * __"Relude.Extra.Newtype"__: generic functions that automatically work for any @newtype@.+* __"Relude.Extra.Tuple"__: functions for working with tuples.+* __"Relude.Extra.Type"__: functions for inspecting and working with types.+* __"Relude.Extra.Validation"__: 'Validation' data type. * __"Relude.Unsafe"__: unsafe partial functions (produce 'error') for lists and 'Maybe'. -}
src/Relude/Bool/Guard.hs view
@@ -13,15 +13,18 @@ , ifM , unlessM , whenM+ , (&&^)+ , (||^) ) where -import Relude.Bool.Reexport (Bool, guard, unless, when)+import Relude.Bool.Reexport (Bool (..), guard, unless, when) import Relude.Function (flip)-import Relude.Monad (Monad, MonadPlus, (>>=))+import Relude.Monad (Monad, return, MonadPlus, (>>=)) -- $setup -- >>> import Relude.Applicative (pure) -- >>> import Relude.Bool.Reexport (Bool (..))+-- >>> import Relude.Debug (error) -- >>> import Relude.Function (($)) -- >>> import Relude.Monad (Maybe (..)) -- >>> import Relude.Print (putTextLn)@@ -73,3 +76,19 @@ guardM :: MonadPlus m => m Bool -> m () guardM f = f >>= guard {-# INLINE guardM #-}++-- | Monadic version of 'Data.Bool.(&&)' operator.+--+-- >>> Just False &&^ error "Shouldn't be evaluated"+-- Just False+(&&^) :: Monad m => m Bool -> m Bool -> m Bool+(&&^) e1 e2 = ifM e1 e2 (return False)+{-# INLINE (&&^) #-}++-- | Monadic version of 'Data.Bool.(||)' operator.+--+-- >>> Just True ||^ error "Shouldn't be evaluated"+-- Just True+(||^) :: Monad m => m Bool -> m Bool -> m Bool+(||^) e1 e2 = ifM e1 (return True) e2+{-# INLINE (||^) #-}
+ src/Relude/Extra/Tuple.hs view
@@ -0,0 +1,62 @@+{- |+Copyright: (c) 2018 Kowainik+License: MIT+Maintainer: Kowainik <xrom.xkov@gmail.com>++Contains utility functions for working with tuples.+-}++module Relude.Extra.Tuple+ ( dupe+ , mapToFst+ , mapToSnd+ , mapBoth+ ) where++-- $setup+-- >>> import Relude++{- | Creates a tuple by pairing something with itself.++>>> dupe "foo"+("foo","foo")+>>> dupe ()+((),())+-}+dupe :: a -> (a, a)+dupe a = (a, a)+{-# INLINE dupe #-}++{- | Apply a function, with the result in the fst slot,+and the value in the other.+++A dual to 'mapToSnd'++>>> mapToFst (+1) 10+(11,10)+-}+mapToFst :: (a -> b) -> a -> (b, a)+mapToFst f a = (f a, a)+{-# INLINE mapToFst #-}++{- | Apply a function, with the result in the second slot,+and the value in the other.++A dual to 'mapToFst'.++>>> mapToSnd (+1) 10+(10,11)+-}+mapToSnd :: (a -> b) -> a -> (a, b)+mapToSnd f a = (a, f a)+{-# INLINE mapToSnd #-}++{- | Maps a function over both elements of a tuple.++>>> mapBoth ("Hello " <>) ("Alice", "Bob")+("Hello Alice","Hello Bob")+-}+mapBoth :: (a -> b) -> (a, a) -> (b, b)+mapBoth f (a1, a2) = (f a1, f a2)+{-# INLINE mapBoth #-}
+ src/Relude/Extra/Type.hs view
@@ -0,0 +1,45 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}++{- |+Copyright: (c) 2018 Kowainik+License: MIT+Maintainer: Kowainik <xrom.xkov@gmail.com>++Contains useful functions to work with Types.+-}++module Relude.Extra.Type+ ( typeName+ ) where++import Relude++#if ( __GLASGOW_HASKELL__ >= 822 )+import Type.Reflection (Typeable, typeRep)+#else+import Data.Typeable (Typeable, typeRep)+#endif++{- | Gets a string representation of a type.++__NOTE:__ This must be used with __TypeApplications__ language extension.++>>> typeName @()+"()"+>>> typeName @Int+"Int"+>>> typeName @String+"[Char]"+>>> typeName @(Maybe Int)+"Maybe Int"+-}+typeName :: forall a. Typeable a => Text+#if ( __GLASGOW_HASKELL__ >= 822 )+typeName = show (typeRep @a)+#else+typeName = show (typeRep (Proxy @a))+#endif+{-# INLINE typeName #-}
+ src/Relude/Extra/Validation.hs view
@@ -0,0 +1,182 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE LambdaCase #-}++{- |+Copyright: (c) 2014 Chris Allen, Edward Kmett+ (c) 2018 Kowainik+License: MIT+Maintainer: Kowainik <xrom.xkov@gmail.com>++Monoidal 'Validation' sibling to 'Either'.+-}++module Relude.Extra.Validation+ ( Validation(..)+ , validationToEither+ , eitherToValidation+ ) where++import Relude++-- $setup+-- >>> :set -XTypeApplications -XOverloadedStrings++-- | 'Validation' is 'Either' with a Left that is a 'Monoid'+data Validation e a+ = Failure e+ | Success a+ deriving (Eq, Ord, Show)++instance Functor (Validation e) where+ fmap :: (a -> b) -> Validation e a -> Validation e b+ fmap _ (Failure e) = Failure e+ fmap f (Success a) = Success (f a)+ {-# INLINE fmap #-}++ (<$) :: a -> Validation e b -> Validation e a+ x <$ Success _ = Success x+ _ <$ Failure e = Failure e+ {-# INLINE (<$) #-}++{- | __Examples__++>>> let fa = Success (*3) :: Validation [Text] (Int -> Int)+>>> let ga = Success (*4) :: Validation [Text] (Int -> Int)+>>> let a = Success 1 :: Validation [Text] Int+>>> let b = Success 7 :: Validation [Text] Int+>>> let c = Failure ["Not correct"] :: Validation [Text] Int+>>> let d = Failure ["Not correct either"] :: Validation [Text] Int++>>> fa <*> b+Success 21++>>> fa <*> c+Failure ["Not correct"]++>>> c *> d *> b+Failure ["Not correct","Not correct either"]++>>> liftA2 (+) a b+Success 8++>>> liftA2 (+) a c+Failure ["Not correct"]+-}+instance Semigroup e => Applicative (Validation e) where+ pure :: a -> Validation e a+ pure = Success+ {-# INLINE pure #-}++#if MIN_VERSION_base(4,10,0)+ liftA2 :: (a -> b -> c) -> Validation e a -> Validation e b -> Validation e c+ liftA2 _ (Failure el) (Failure er) = Failure (el <> er)+ liftA2 _ (Failure e) (Success _) = Failure e+ liftA2 _ (Success _) (Failure e) = Failure e+ liftA2 f (Success a) (Success b) = Success (f a b)+ {-# INLINE liftA2 #-}+#endif++ (<*>) :: Validation e (a -> b) -> Validation e a -> Validation e b+ Failure e <*> b = Failure $ case b of+ Failure e' -> e <> e'+ Success _ -> e+ Success _ <*> Failure e = Failure e+ Success f <*> Success a = Success (f a)+ {-# INLINE (<*>) #-}++ (*>) :: Validation e a -> Validation e b -> Validation e b+ Failure el *> Failure er = Failure (el <> er)+ Failure e *> Success _ = Failure e+ Success _ *> Failure e = Failure e+ Success _ *> Success b = Success b+ {-# INLINE (*>) #-}++ (<*) :: Validation e a -> Validation e b -> Validation e a+ Failure el <* Failure er = Failure (el <> er)+ Failure e <* Success _ = Failure e+ Success _ <* Failure e = Failure e+ Success a <* Success _ = Success a+ {-# INLINE (<*) #-}++instance (Semigroup e, Monoid e) => Alternative (Validation e) where+ empty :: Validation e a+ empty = Failure mempty+ {-# INLINE empty #-}++ (<|>) :: Validation e a -> Validation e a -> Validation e a+ s@Success{} <|> _ = s+ _ <|> s@Success{} = s+ Failure e <|> Failure e' = Failure (e <> e')+ {-# INLINE (<|>) #-}++instance Foldable (Validation e) where+ fold :: Monoid m => Validation e m -> m+ fold (Success a) = a+ fold (Failure _) = mempty+ {-# INLINE fold #-}++ foldMap :: Monoid m => (a -> m) -> Validation e a -> m+ foldMap _ (Failure _) = mempty+ foldMap f (Success a) = f a+ {-# INLINE foldMap #-}++ foldr :: (a -> b -> b) -> b -> Validation e a -> b+ foldr f x (Success a) = f a x+ foldr _ x (Failure _) = x+ {-# INLINE foldr #-}++instance Traversable (Validation e) where+ traverse :: Applicative f => (a -> f b) -> Validation e a -> f (Validation e b)+ traverse f (Success a) = Success <$> f a+ traverse _ (Failure e) = pure (Failure e)+ {-# INLINE traverse #-}++ sequenceA :: Applicative f => Validation e (f a) -> f (Validation e a)+ sequenceA = traverse id+ {-# INLINE sequenceA #-}++instance Bifunctor Validation where+ bimap :: (e -> d) -> (a -> b) -> Validation e a -> Validation d b+ bimap f _ (Failure e) = Failure (f e)+ bimap _ g (Success a) = Success (g a)+ {-# INLINE bimap #-}++ first :: (e -> d) -> Validation e a -> Validation d a+ first f (Failure e) = Failure (f e)+ first _ (Success a) = Success a+ {-# INLINE first #-}++ second :: (a -> b) -> Validation e a -> Validation e b+ second _ (Failure e) = Failure e+ second g (Success a) = Success (g a)+ {-# INLINE second #-}++#if MIN_VERSION_base(4,10,0)+instance Bifoldable Validation where+ bifoldMap :: Monoid m => (e -> m) -> (a -> m) -> Validation e a -> m+ bifoldMap f _ (Failure e) = f e+ bifoldMap _ g (Success a) = g a+ {-# INLINE bifoldMap #-}++instance Bitraversable Validation where+ bitraverse :: Applicative f+ => (e -> f d) -> (a -> f b) -> Validation e a -> f (Validation d b)+ bitraverse f _ (Failure e) = Failure <$> f e+ bitraverse _ g (Success a) = Success <$> g a+ {-# INLINE bitraverse #-}+#endif++-- | Transform a 'Validation' into an 'Either'.+validationToEither :: Validation e a -> Either e a+validationToEither = \case+ Failure e -> Left e+ Success a -> Right a+{-# INLINE validationToEither #-}++-- | Transform an 'Either' into a 'Validation'.+eitherToValidation :: Either e a -> Validation e a+eitherToValidation = \case+ Left e -> Failure e+ Right a -> Success a+{-# INLINE eitherToValidation #-}
src/Relude/Foldable/Fold.hs view
@@ -20,6 +20,7 @@ module Relude.Foldable.Fold ( flipfoldl' , foldMapA+ , asumMap , foldMapM , sum , product@@ -39,7 +40,7 @@ import GHC.TypeLits (ErrorMessage (..), TypeError) -import Relude.Applicative (Applicative (..), pure)+import Relude.Applicative (Alternative, Applicative (..), pure) import Relude.Base (Constraint, Eq, IO, Num (..), Type, ($!)) import Relude.Bool (Bool (..)) import Relude.Container.Reexport (HashSet, Set)@@ -47,7 +48,7 @@ import Relude.Function (flip, (.)) import Relude.Functor ((<$>)) import Relude.Monad.Reexport (Monad (..))-import Relude.Monoid (Monoid (..))+import Relude.Monoid (Alt(..), Monoid (..)) import qualified Data.Foldable as F @@ -75,6 +76,14 @@ where step a mb = mappend <$> f a <*> mb {-# INLINE foldMapA #-}++{- | Alternative version of @asum@+>>> asumMap (\x -> if x > 2 then Just x else Nothing) [1..3]+Just 3+-}+asumMap :: (Foldable f, Alternative m) => (a -> m b) -> f a -> m b+asumMap f = getAlt . foldMap (Alt . f)+{-# INLINE asumMap #-} {- | Polymorphic version of @concatMapM@ function.
src/Relude/Foldable/Reexport.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE CPP #-}+ {- | Copyright: (c) 2018 Kowainik License: MIT@@ -9,9 +11,20 @@ module Relude.Foldable.Reexport ( module Data.Foldable , module Data.Traversable+#if MIN_VERSION_base(4,10,0)+ , module Data.Bifoldable+ , module Data.Bitraversable+#endif ) where import Data.Foldable (Foldable (fold, foldMap, foldl', foldr, length, null, toList), all, and, any, asum, concat, concatMap, find, foldlM, forM_, for_, mapM_, or, sequenceA_, sequence_, traverse_) import Data.Traversable (Traversable (..), forM, mapAccumL, mapAccumR)+#if MIN_VERSION_base(4,10,0)+import Data.Bifoldable (Bifoldable (..), biList, biall, biand,+ biany, biasum, bielem, bifind, bifoldl', bifoldlM, bifoldr',+ bifoldrM, bifor_, bilength, binull, bior, bisequence_,+ bitraverse_)+import Data.Bitraversable (Bitraversable (..), bifoldMapDefault, bifor, bimapDefault, bisequence)+#endif
src/Relude/Functor/Reexport.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE Safe #-} {- |@@ -15,9 +16,18 @@ , module Data.Functor , module Data.Functor.Compose , module Data.Functor.Identity+#if MIN_VERSION_base(4,12,0)+ , module Data.Functor.Contravariant+#endif ) where import Data.Bifunctor (Bifunctor (..)) import Data.Functor (Functor (..), void, ($>), (<$>)) import Data.Functor.Compose (Compose (..)) import Data.Functor.Identity (Identity (..))++#if MIN_VERSION_base(4,12,0)+import Data.Functor.Contravariant (Comparison (..), Contravariant (..), Equivalence (..), Op (..),+ Predicate (..), comparisonEquivalence, defaultComparison,+ defaultEquivalence, phantom, ($<), (>$$<), (>$<))+#endif
src/Relude/Lifted/File.hs view
@@ -12,11 +12,9 @@ ( readFile , writeFile , appendFile- , openFile- , hClose ) where -import Relude.Base (FilePath, Handle, IO, IOMode, String)+import Relude.Base (FilePath, IO, String) import Relude.Function ((.)) import Relude.Monad.Reexport (MonadIO (..)) @@ -40,15 +38,3 @@ appendFile p = liftIO . IO.appendFile p {-# SPECIALIZE appendFile :: FilePath -> String -> IO () #-} {-# INLINE appendFile #-}---- | Lifted version of 'IO.openFile'.-openFile :: MonadIO m => FilePath -> IOMode -> m Handle-openFile p = liftIO . IO.openFile p-{-# SPECIALIZE openFile :: FilePath -> IOMode -> IO Handle #-}-{-# INLINE openFile #-}---- | Lifted version of 'IO.hClose'.-hClose :: MonadIO m => Handle -> m ()-hClose = liftIO . hClose-{-# SPECIALIZE hClose :: Handle -> IO () #-}-{-# INLINE hClose #-}
src/Relude/Nub.hs view
@@ -43,7 +43,7 @@ import qualified Data.Set as Set -{- | Like 'Prelude.nub' but runs in @O(n * log n)@ time and requires 'Ord'.+{- | Like 'Prelude.nub' but runs in \( O(n \log n) \) time and requires 'Ord'. >>> ordNub [3, 3, 3, 2, 2, -1, 1] [3,2,-1,1]@@ -58,7 +58,7 @@ then go s xs else x : go (Set.insert x s) xs -{- | Like 'Prelude.nub' but runs in @O(n * log_16(n))@ time and requires 'Hashable'.+{- | Like 'Prelude.nub' but runs in \( O(n \log_{16} n) \) time and requires 'Hashable'. >>> hashNub [3, 3, 3, 2, 2, -1, 1] [3,2,-1,1]@@ -73,7 +73,7 @@ then go s xs else x : go (HashSet.insert x s) xs -{- | Like 'ordNub' but also sorts a list.+{- | Like 'ordNub' runs in \( O(n \log n) \) but also sorts a list. >>> sortNub [3, 3, 3, 2, 2, -1, 1] [-1,1,2,3]@@ -82,7 +82,7 @@ sortNub :: (Ord a) => [a] -> [a] sortNub = Set.toList . Set.fromList -{- | Like 'hashNub' but has better performance and also doesn't save the order.+{- | Like 'hashNub' runs in \( O(n \log_{16} n) \) but has better performance; it doesn't save the order. >>> unstableNub [3, 3, 3, 2, 2, -1, 1] [1,2,3,-1]
src/Relude/String/Conversion.hs view
@@ -48,8 +48,6 @@ import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as LB-import qualified Data.ByteString.Lazy.UTF8 as LBU-import qualified Data.ByteString.UTF8 as BU import qualified Data.Text as T import qualified Data.Text.Encoding as T import qualified Data.Text.Encoding.Error as T@@ -101,8 +99,8 @@ decodeUtf8Strict :: b -> Either T.UnicodeException a instance ConvertUtf8 String B.ByteString where- encodeUtf8 = BU.fromString- decodeUtf8 = BU.toString+ encodeUtf8 = T.encodeUtf8 . T.pack+ decodeUtf8 = T.unpack . T.decodeUtf8 decodeUtf8Strict = (T.unpack <$>) . decodeUtf8Strict instance ConvertUtf8 T.Text B.ByteString where@@ -114,10 +112,11 @@ encodeUtf8 = LB.toStrict . encodeUtf8 decodeUtf8 = LT.decodeUtf8With T.lenientDecode . LB.fromStrict decodeUtf8Strict = decodeUtf8Strict . LB.fromStrict-+-- | Converting 'String' to 'LB.ByteString' might be a slow operation.+-- Consider using lazy bytestring at first place. instance ConvertUtf8 String LB.ByteString where- encodeUtf8 = LBU.fromString- decodeUtf8 = LBU.toString+ encodeUtf8 = LT.encodeUtf8 . LT.pack+ decodeUtf8 = LT.unpack . LT.decodeUtf8 decodeUtf8Strict = (T.unpack <$>) . decodeUtf8Strict instance ConvertUtf8 T.Text LB.ByteString where