universum 1.7.3 → 1.8.3.1
raw patch · 28 files changed
Files
- CHANGES.md +74/−1
- CONTRIBUTING.md +2/−2
- README.md +2/−4
- benchmark/Main.hs +5/−8
- src/Universum.hs +118/−5
- src/Universum/Base.hs +9/−4
- src/Universum/Container/Class.hs +28/−3
- src/Universum/Debug.hs +1/−1
- src/Universum/Exception.hs +1/−0
- src/Universum/Function.hs +1/−1
- src/Universum/Functor/Reexport.hs +1/−1
- src/Universum/List/Reexport.hs +2/−2
- src/Universum/Monad/Container.hs +4/−0
- src/Universum/Monad/Reexport.hs +1/−1
- src/Universum/Monoid.hs +2/−2
- src/Universum/String/Conversion.hs +28/−19
- src/Universum/String/Reexport.hs +1/−1
- src/Universum/TypeOps.hs +12/−9
- src/Universum/VarArg.hs +7/−0
- test/Spec.hs +3/−5
- test/Test/Universum/BoolMProps.hs +22/−0
- test/Test/Universum/Issue208.hs +23/−0
- test/Test/Universum/ListProps.hs +35/−0
- test/Test/Universum/Property.hs +0/−177
- test/Test/Universum/StringProps.hs +55/−0
- test/Test/Universum/UtfProps.hs +64/−0
- test/Tree.hs +1/−0
- universum.cabal +41/−23
CHANGES.md view
@@ -1,5 +1,78 @@-Unreleased+1.8.3.1+=======++* [#304](https://github.com/serokell/universum/pull/304)+ * Add support for GHC-9.14 without any user-visible changes.++1.8.3+=======++* [#301](https://github.com/serokell/universum/pull/301)+ * Relax the upper bound on `text`.+* [#300](https://github.com/serokell/universum/pull/300)+ * Fix building with microlens-0.5.++1.8.2.2+=======++* [#297](https://github.com/serokell/universum/pull/297)+ * Add support for GHC-9.10 without any user-visible changes.++1.8.2.1+=======++* [#293](https://github.com/serokell/universum/pull/293)+ * Add explicit kind signatures for custom operators.+ * Bump some dependency constraints to support GHC-9.8.++1.8.2 =====++* [#289](https://github.com/serokell/universum/pull/289):+ Make universum work with LTS-21.0.+ * Re-export `(~)` type operator.+* [#283](https://github.com/serokell/universum/pull/283):+ Bump the upper version bound on `text` to `2.0.2`.++1.8.1.1+=======++* [#282](https://github.com/serokell/universum/pull/282):+ Bump the upper version bound on `text` to `2.0.1`.++1.8.1+=====++* [#271](https://github.com/serokell/universum/pull/271):+ Add compatibility with tasty-hedgehog 1.2.0.0++1.8.0+=====++* [#252](https://github.com/serokell/universum/pull/252):+ Remove `Option` re-export. Use `Maybe` instead.++* [#176](https://github.com/serokell/universum/issues/176):+ Deprecate `note`.++* [#206](https://github.com/serokell/universum/issues/206):+ Remove `listToMaybe`.+ _Migration guide:_ use `safeHead` directly with functions from+ `Universum.Container` instead.++* [#182](https://github.com/serokell/universum/issues/182):+ Deprecate `microlens` and `microlens-mtl` dependencies.++* [#165](https://github.com/serokell/universum/issues/165):+ Change the type of `readMaybe` from `readMaybe :: Read a => String -> Maybe a`+ to it's polymorphic version `readMaybe :: forall b a. (ToString a, Read b) => a -> Maybe b`.++* [#199](https://github.com/serokell/universum/issues/199):+ Change type of `concatMap` from `concatMap :: Foldable f => (a -> [b]) -> t a -> [b]`+ to `concatMap :: Container c => (Element c -> [b]) -> c -> [b]`.++* [250](https://github.com/serokell/universum/issues):+ Replace `group` export from `Data.List` with `group`, `groupBy`, `groupWith` and `groupAllWith` from `Data.List.NonEmpty`. 1.7.3 =====
CONTRIBUTING.md view
@@ -66,8 +66,8 @@ However, 4 approvals (at least 3 from Serokell) are necessary for inclusion into a milestone. 2 disapprovals from Serokell or 4 disapprovals in total are enough to prevent the issue from getting into a milestone. If an issue is about removal of something (`x`), it should be done in two steps.-The first step is deprecation of `x` which happens in a `breaking` release.-The second step is deprecation of `x` which happens in another `breaking` release after deprecation of `x`.+The first step is to deprecate `x` which happens in a `breaking` release.+The second step is to delete `x` which happens in another `breaking` release after deprecating `x`. There can't be more than one breaking release in less than 5 weeks. Note: approval of any PR implies that the person who approves it confirms that the PR corresponds to the issue mentioned there and the issue has a correct type.
README.md view
@@ -54,8 +54,7 @@ new basic set of defaults. There already were plenty of [preludes](https://guide.aelve.com/haskell/alternative-preludes-zr69k1hc), so we didn't plan to implement everything from scratch. After some long, hot discussions, our team decided to base our custom prelude on-[`protolude`](https://github.com/sdiehl/protolude). If you're not familiar with it,-you can read [a tutorial about `protolude`](http://www.stephendiehl.com/posts/protolude.html).+[`protolude`](https://github.com/protolude/protolude). The next section explains why we've made this choice and what we are willing to do. This tutorial doesn't cover the differences from `protolude`. Instead, it explains how Universum is different from regular `Prelude`.@@ -77,8 +76,7 @@ Instead, we reexport common and well-known things from `base` and some other libraries that are used in everyday production programming in _Haskell_. > **Note**: well, we did end up inventing _some_ new things.-4. Export more useful and commonly used functions. [Hello, my name is Dmitry. I was- coding _Haskell_ for 3 years but still hoogling which module `liftIO` comes from.](https://twitter.com/magnars/status/834683466130345984)+4. Export more useful and commonly used functions. Things like `liftIO`, `ReaderT` type, `MVar`-related functions have unambiguous names, are used in almost every non-trivial project, and it's really tedious to import them manually every time.
benchmark/Main.hs view
@@ -72,7 +72,7 @@ ] groupSort :: [a] -> [a]- groupSort = map Unsafe.head . group . sort+ groupSort = map NonEmpty.head . group . sort safeSort :: [a] -> [a] safeSort = map NonEmpty.head . NonEmpty.group . sort@@ -180,11 +180,8 @@ bgroupTextConversion :: Benchmark bgroupTextConversion = bgroup "text conversions"- [ let str = replicate 100000 'a'- countLength x = length (toString x)- in bench "toString . toText" $ whnf (countLength . toText) str-- , let txt = T.replicate 100000 (T.singleton 'a')- countLength x = length (toText x)- in bench "toText . toString" $ whnf (countLength . toString) txt+ [ -- With @toText . toString -> id@ rewrite rules we expect ~10ns+ -- Without the rules: >10ms+ let txt = T.replicate 10000000 (T.singleton 'a')+ in bench "toText . toString" $ whnf (toText . toString) txt ]
src/Universum.hs view
@@ -1,4 +1,6 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE Trustworthy #-}+{-# LANGUAGE RankNTypes #-} {- | Main module that reexports all functionality allowed to use without importing any other modules. Just add next lines to your@@ -80,8 +82,26 @@ , module Universum.VarArg -- * Lenses- , module Lens.Micro- , module Lens.Micro.Mtl+ , Lens+ , Lens'+ , Traversal+ , Traversal'+ , over+ , set+ , (%~)+ , (.~)+ , (^.)+ , (^..)+ , (^?)+ , _1+ , _2+ , _3+ , _4+ , _5+ , preuse+ , preview+ , use+ , view ) where import Universum.Applicative@@ -104,6 +124,99 @@ import Universum.VarArg -- Lenses-import Lens.Micro (Lens, Lens', Traversal, Traversal', over, set, (%~), (&), (.~), (<&>), (^.),- (^..), (^?), _1, _2, _3, _4, _5)-import Lens.Micro.Mtl (preuse, preview, use, view)+import qualified Lens.Micro (ASetter, Getting, over, set, (%~), (.~), (^.),+ (^..), (^?), _1, _2, _3, _4, _5)+import qualified Lens.Micro.Mtl (preuse, preview, use, view)+#if MIN_VERSION_microlens(0,5,0)+import Lens.Micro (Field1, Field2, Field3, Field4, Field5)+#else+import Lens.Micro.Internal (Field1, Field2, Field3, Field4, Field5)+#endif++{-# DEPRECATED+ Lens+ , Lens'+ , Traversal+ , Traversal'+ , over+ , set+ , (%~)+ , (.~)+ , (^.)+ , (^..)+ , (^?)+ , _1+ , _2+ , _3+ , _4+ , _5+ , preuse+ , preview+ , use+ , view+ "Use corresponding function from 'lens' or 'microlens' package"+#-}++type Lens s t a b = forall f. Functor f => (a -> f b) -> s -> f t+type Lens' s a = Lens s s a a++type Traversal s t a b = forall f. Applicative f => (a -> f b) -> s -> f t+type Traversal' s a = Traversal s s a a++over :: Lens.Micro.ASetter s t a b -> (a -> b) -> s -> t+over = Lens.Micro.over++set :: Lens.Micro.ASetter s t a b -> b -> s -> t+set = Lens.Micro.set++(%~) :: Lens.Micro.ASetter s t a b -> (a -> b) -> s -> t+(%~) = (Lens.Micro.%~)++infixr 4 %~++(.~) :: Lens.Micro.ASetter s t a b -> b -> s -> t+(.~) = (Lens.Micro..~)++infixr 4 .~++(^.) :: s -> Lens.Micro.Getting a s a -> a+(^.) = (Lens.Micro.^.)++infixl 8 ^.++(^..) :: s -> Lens.Micro.Getting (Endo [a]) s a -> [a]+(^..) = (Lens.Micro.^..)++infixl 8 ^..++(^?) :: s -> Lens.Micro.Getting (First a) s a -> Maybe a+(^?) = (Lens.Micro.^?)++infixl 8 ^?++_1 :: Field1 s t a b => Lens s t a b+_1 = Lens.Micro._1++_2 :: Field2 s t a b => Lens s t a b+_2 = Lens.Micro._2++_3 :: Field3 s t a b => Lens s t a b+_3 = Lens.Micro._3++_4 :: Field4 s t a b => Lens s t a b+_4 = Lens.Micro._4++_5 :: Field5 s t a b => Lens s t a b+_5 = Lens.Micro._5++preuse :: MonadState s m => Lens.Micro.Getting (First a) s a -> m (Maybe a)+preuse = Lens.Micro.Mtl.preuse++preview :: MonadReader s m => Lens.Micro.Getting (First a) s a -> m (Maybe a)+preview = Lens.Micro.Mtl.preview++use :: MonadState s m => Lens.Micro.Getting a s a -> m a+use = Lens.Micro.Mtl.use++view :: MonadReader s m => Lens.Micro.Getting a s a -> m a+view = Lens.Micro.Mtl.view
src/Universum/Base.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE BangPatterns #-} {-# LANGUAGE Unsafe #-} @@ -24,6 +25,9 @@ , module Data.Proxy , module Data.Typeable , module Data.Void+#if MIN_VERSION_base(4,17,0)+ , module Data.Type.Equality+#endif , module GHC.Base , module GHC.Enum@@ -34,7 +38,6 @@ , module GHC.Real , module GHC.Show , module GHC.TypeNats- , module GHC.Types , module GHC.OverloadedLabels , module GHC.ExecutionStack , module GHC.Stack@@ -58,7 +61,7 @@ -- Base typeclasses import Data.Eq (Eq (..))-import Data.Foldable (Foldable, concat, concatMap, foldlM, foldrM)+import Data.Foldable (Foldable, concat, foldlM, foldrM) import Data.Kind (Constraint, Type) import Data.Ord (Down (..), Ord (..), Ordering (..), comparing) import Data.Traversable (Traversable (..), fmapDefault, foldMapDefault, forM, mapAccumL, mapAccumR)@@ -67,8 +70,11 @@ import Data.Proxy (Proxy (..)) import Data.Typeable (Typeable) import Data.Void (Void, absurd, vacuous)+#if MIN_VERSION_base(4,17,0)+import Data.Type.Equality (type (~))+#endif -import GHC.Base (String, asTypeOf, maxInt, minInt, ord, seq)+import GHC.Base (Bool, Char, Coercible, IO, Int, Ordering, String, Word, asTypeOf, maxInt, minInt, ord, seq) import GHC.Enum (Bounded (..), Enum (..), boundedEnumFrom, boundedEnumFromThen) import GHC.ExecutionStack (getStackTrace, showStackTrace) import GHC.Exts (FunPtr, Ptr)@@ -81,7 +87,6 @@ import GHC.Stack (CallStack, HasCallStack, callStack, currentCallStack, getCallStack, prettyCallStack, prettySrcLoc, withFrozenCallStack) import GHC.TypeNats (CmpNat, KnownNat, Nat, SomeNat (..), natVal, someNatVal)-import GHC.Types (Bool, Char, Coercible, IO, Int, Ordering, Word) -- $setup -- >>> import Universum.Function (const, ($))
src/Universum/Container/Class.hs view
@@ -39,6 +39,7 @@ , sequenceA_ , sequence_ , asum+ , concatMap -- * Others , One(..)@@ -46,8 +47,11 @@ import Data.Coerce (Coercible, coerce) import Data.Kind (Type)-import Prelude hiding (all, and, any, elem, foldMap, foldl, foldr, mapM_, notElem, null, or, print,- product, sequence_, sum)+import Prelude hiding (all, and, any, concatMap, elem, foldMap, foldl, foldr, mapM_, notElem, null,+#if __GLASGOW_HASKELL__ >= 910+ foldl',+#endif+ or, print, product, sequence_, sum) import Universum.Applicative (Alternative (..), Const, ZipList (..), pass) import Universum.Base (HasCallStack, Word8)@@ -69,6 +73,8 @@ import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as BSL +import qualified Data.List (concatMap)+ import qualified Data.Text as T import qualified Data.Text.Lazy as TL @@ -228,9 +234,13 @@ instance FromList IntSet instance Ord a => FromList (Set a)-instance (Eq k, Hashable k) => FromList (HashMap k v) instance FromList (IntMap v) instance Ord k => FromList (Map k v)+#if MIN_VERSION_hashable(1,4,0)+instance (Hashable k) => FromList (HashMap k v)+#else+instance (Eq k, Hashable k) => FromList (HashMap k v)+#endif instance FromList T.Text instance FromList TL.Text@@ -572,7 +582,11 @@ notElem = Set.notMember {-# INLINE notElem #-} +#if MIN_VERSION_hashable(1,4,0)+instance (Hashable v) => Container (HashSet v) where+#else instance (Eq v, Hashable v) => Container (HashSet v) where+#endif elem = HashSet.member {-# INLINE elem #-} @@ -745,6 +759,17 @@ => t -> f a asum = foldr (<|>) empty {-# INLINE asum #-}++{- | Version of 'Data.Foldable.concatMap' constrained to 'Container'.++>>> concatMap (\x -> [x + 1, x + 2]) [1, 2, 3]+[2,3,3,4,4,5]++@since 1.8.0+-}+concatMap :: Container c => (Element c -> [b]) -> c -> [b]+concatMap f = Data.List.concatMap f . toList+{-# INLINE concatMap #-} ---------------------------------------------------------------------------- -- Disallowed instances
src/Universum/Debug.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DerivingStrategies #-}@@ -8,7 +9,6 @@ {-# LANGUAGE PolyKinds #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE Trustworthy #-}-{-# LANGUAGE TypeInType #-} -- | Functions for debugging. If you left these functions in your code -- then warning is generated to remind you about left usages. Also, some
src/Universum/Exception.hs view
@@ -47,6 +47,7 @@ -- To suppress redundant applicative constraint warning on GHC 8.0 -- | Throws error for 'Maybe' if 'Data.Maybe.Nothing' is given. -- Operates over 'MonadError'.+{-# DEPRECATED note "Don't use this function. Use 'maybeToRight' instead" #-} note :: (MonadError e m) => e -> Maybe a -> m a note err = maybe (throwError err) pure
src/Universum/Function.hs view
@@ -6,4 +6,4 @@ ( module Data.Function ) where -import Data.Function (const, fix, flip, id, on, ($), (.))+import Data.Function (const, fix, flip, id, on, ($), (.), (&))
src/Universum/Functor/Reexport.hs view
@@ -12,6 +12,6 @@ import Control.Arrow ((&&&)) import Data.Bifunctor (Bifunctor (..))-import Data.Functor (Functor (..), void, ($>), (<$>))+import Data.Functor (Functor (..), void, ($>), (<$>), (<&>)) import Data.Functor.Compose (Compose (..)) import Data.Functor.Identity (Identity (..))
src/Universum/List/Reexport.hs view
@@ -9,10 +9,10 @@ ) where import Data.List (break, cycle, drop, dropWhile, filter, genericDrop, genericLength,- genericReplicate, genericSplitAt, genericTake, group, inits, intercalate,+ genericReplicate, genericSplitAt, genericTake, inits, intercalate, intersperse, isPrefixOf, iterate, permutations, repeat, replicate, reverse, scanl, scanr, sort, sortBy, sortOn, splitAt, subsequences, tails, take, takeWhile, transpose, unfoldr, unzip, unzip3, zip, zip3, zipWith, (++))-import Data.List.NonEmpty (NonEmpty (..), head, init, last, nonEmpty, tail)+import Data.List.NonEmpty (NonEmpty (..), group, groupAllWith, groupBy, groupWith, head, init, last, nonEmpty, tail) import GHC.Exts (sortWith)
src/Universum/Monad/Container.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE Trustworthy #-} {-# LANGUAGE TypeFamilies #-} @@ -18,6 +19,9 @@ import Data.Function ((.)) import Data.Traversable (Traversable (traverse)) import Prelude (Bool (..), Monoid, flip)+#if MIN_VERSION_base(4,17,0)+import Data.Type.Equality (type (~))+#endif import Universum.Base (IO) import Universum.Container (Container, Element, fold, toList)
src/Universum/Monad/Reexport.hs view
@@ -57,7 +57,7 @@ import Control.Monad.Trans.Maybe (MaybeT (..), exceptToMaybeT, maybeToExceptT) -- Maybe-import Data.Maybe (Maybe (..), catMaybes, fromMaybe, isJust, isNothing, listToMaybe, mapMaybe,+import Data.Maybe (Maybe (..), catMaybes, fromMaybe, isJust, isNothing, mapMaybe, maybe, maybeToList) -- Either
src/Universum/Monoid.hs view
@@ -10,8 +10,8 @@ import Data.Monoid (All (..), Alt (..), Any (..), Dual (..), Endo (..), First (..), Last (..), Monoid (..), Product (..), Sum (..))-import Data.Semigroup (Option (..), Semigroup (sconcat, stimes, (<>)), WrappedMonoid, cycle1,- mtimesDefault, stimesIdempotent, stimesIdempotentMonoid, stimesMonoid)+import Data.Semigroup (Semigroup (sconcat, stimes, (<>)), WrappedMonoid, cycle1, mtimesDefault,+ stimesIdempotent, stimesIdempotentMonoid, stimesMonoid) import Universum.Monad.Reexport (Maybe, fromMaybe)
src/Universum/String/Conversion.hs view
@@ -3,7 +3,6 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE Trustworthy #-}-{-# LANGUAGE TypeSynonymInstances #-} {-# OPTIONS_GHC -Wno-orphans #-} -- | This module implements type class which allow to have conversion to and@@ -25,15 +24,20 @@ -- * Show and read functions , readEither+ , readMaybe , show ) where import Data.Bifunctor (first) import Data.Either (Either) import Data.Function (id, (.))+import Data.Maybe (Maybe) import Data.String (String) import qualified Data.Text.Internal as T++#if !MIN_VERSION_text(2,0,2) import qualified Data.Text.Internal.Fusion.Common as TF+#endif import Universum.Functor ((<$>)) import Universum.String.Reexport (ByteString, IsString, Read, Text, fromString)@@ -47,7 +51,7 @@ import qualified Data.Text.Encoding.Error as T import qualified Data.Text.Lazy as LT import qualified Data.Text.Lazy.Encoding as LT-import qualified Text.Read (readEither)+import qualified Text.Read (readEither, readMaybe) import qualified GHC.Show as Show (Show (show)) @@ -170,32 +174,25 @@ there are still some libraries which use 'String's and thus make us perform conversions back and forth. -Note that @toString . toText@ is not strictly equal to identity function, see-explanation in the comment below.+Note that, as documentation for 'T.pack' function mentions, @toString . toText@+is not strictly equal to the identity function. Thus, replacing @toString . toText@+with @id@ will result in losing transformation of surrogate code points.+But in the most cases this is what the user wants. -} {-# RULES "pack/unpack" [~0] forall s. T.unpack (T.pack s) = s #-} -{- [Note toString-toText-rewritting]+-- This applies when `text` is older than 2.0.2, the oldest GHC version+-- with such `text` is 9.4.4+-- TODO: remove once we stop supporting GHC 9.4 and older.+#if !MIN_VERSION_text(2,0,2)+{- We can do even better than above if take rules defined in 'Data.Text' into account. -Note ON MAINTENANCE: whenever you need to update the used version of @text@ package,-you have to check whether the comment below is still valid.-However, you can cut down by looking at the diff between versions of @text@, and-seeing if implementation of any of these functions have changed:- * pack- * unpack- * streamList- * unstreamList- * safe- * any RULES definition (if some is added, this counts)-If none of mentioned have changed, then it is safe to assume that everything-is still fine.- Quoting investigation of @int-index: If we look at @unpack@ and @pack@ they are defined as@@ -245,7 +242,7 @@ There's a comment on top of it to explain this: ```--- UTF-16 surrogate code points are not included in the set of Unicode+-- Unicode 'Data.Char.Surrogate' code points are not included in the set of Unicode -- scalar values, but are unfortunately admitted as valid 'Char' -- values by Haskell. They cannot be represented in a 'Text'. This -- function remaps those code points to the Unicode replacement@@ -266,6 +263,7 @@ {-# RULES "pack/unpack internal" [1] forall s. TF.unstreamList (TF.map T.safe (TF.streamList s)) = s #-}+#endif {- In case if GHC didn't manage to inline and rewrite everything in the remaining phases (@Data.Text.pack@ is inlined at 1-st phase),@@ -290,8 +288,19 @@ -- Right 123 -- >>> readEither @Text @Int "aa" -- Left "Prelude.read: no parse"+--+-- @since 1.8.0 readEither :: (ToString a, Read b) => a -> Either Text b readEither = first toText . Text.Read.readEither . toString++-- | Polymorhpic version of 'Text.Read.readMaybe'.+--+-- >>> readMaybe @Int @Text "123"+-- Just 123+-- >>> readMaybe @Int @Text "aa"+-- Nothing+readMaybe :: forall b a. (ToString a, Read b) => a -> Maybe b+readMaybe = Text.Read.readMaybe . toString -- | Generalized version of 'Prelude.show'. show :: forall b a . (Show.Show a, IsString b) => a -> b
src/Universum/String/Reexport.hs view
@@ -24,4 +24,4 @@ import Data.Text.Encoding.Error (OnDecodeError, OnError, UnicodeException, lenientDecode, strictDecode) import Data.Text.Lazy (fromStrict, toStrict)-import Text.Read (Read, readMaybe, reads)+import Text.Read (Read, reads)
src/Universum/TypeOps.hs view
@@ -1,12 +1,13 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE ExplicitNamespaces #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE Safe #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE ExplicitNamespaces #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE Safe #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE StandaloneKindSignatures #-}+{-# LANGUAGE TypeOperators #-} -- | Type operators for writing convenient type signatures. @@ -25,6 +26,7 @@ -- = -- f :: Either String (Maybe Int) -- @+type ($) :: (k2 -> k1) -> k2 -> k1 type f $ a = f a infixr 2 $ @@ -66,4 +68,5 @@ -- = -- a :: (Show a, Read a) => a -> a -- @+type With :: [k -> Constraint] -> k -> Constraint type With a b = a <+> b
src/Universum/VarArg.hs view
@@ -1,8 +1,11 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE Safe #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} -- | Provides operator of variable-arguments function composition.@@ -10,6 +13,10 @@ module Universum.VarArg ( SuperComposition(..) ) where++#if MIN_VERSION_base(4,17,0)+import Data.Type.Equality (type (~))+#endif -- $setup -- >>> import Universum.Base ((+))
test/Spec.hs view
@@ -2,10 +2,8 @@ ( main ) where -import Test.Tasty (defaultMain)--import Test.Universum.Property (hedgehogTestTree)+import Test.Tasty+import Tree (tests) main :: IO ()-main = do- defaultMain hedgehogTestTree+main = tests >>= defaultMain
+ test/Test/Universum/BoolMProps.hs view
@@ -0,0 +1,22 @@+module Test.Universum.BoolMProps+ ( hprop_andM+ , hprop_orM+ ) where++import Hedgehog (Gen, Property, forAll, property, (===))+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range+import qualified Universum as U++genBoolList :: Gen [U.Bool]+genBoolList = Gen.list (Range.linear 0 1000) Gen.bool++hprop_andM :: Property+hprop_andM = property $ do+ bs <- forAll genBoolList+ U.andM (return <$> bs) === ((return $ U.and bs) :: U.Maybe U.Bool)++hprop_orM :: Property+hprop_orM = property $ do+ bs <- forAll genBoolList+ U.orM (return <$> bs) === ((return $ U.or bs) :: U.Maybe U.Bool)
+ test/Test/Universum/Issue208.hs view
@@ -0,0 +1,23 @@+{-# LANGUAGE+ GeneralizedNewtypeDeriving+ , UndecidableInstances+ , FlexibleContexts+ , GADTs+ , DerivingStrategies+ , CPP+#-}+module Test.Universum.Issue208+ () where++#if __GLASGOW_HASKELL__ >= 900++import Universum (Container)++-- In ghc-8.6.3 this code will produce a @redundant constraint@ warning.+-- In ghc-9.0.2 and newer no warnings would be produced.+-- Issue #208: https://github.com/serokell/universum/issues/208++newtype Test = Test [Int]+ deriving newtype (Container)++#endif
+ test/Test/Universum/ListProps.hs view
@@ -0,0 +1,35 @@+module Test.Universum.ListProps+ ( hprop_ordNubCorrect+ , hprop_hashNubCorrect+ , hprop_sortNubCorrect+ , hprop_unstableNubCorrect+ ) where++import Data.List (nub)+import Hedgehog (Gen, Property, forAll, property, (===))+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range+import qualified Universum as U++genIntList :: Gen [U.Int]+genIntList = Gen.list (Range.linear 0 10000) Gen.enumBounded++hprop_ordNubCorrect :: Property+hprop_ordNubCorrect = property $ do+ xs <- forAll genIntList+ U.ordNub xs === nub xs++hprop_hashNubCorrect :: Property+hprop_hashNubCorrect = property $ do+ xs <- forAll genIntList+ U.hashNub xs === nub xs++hprop_sortNubCorrect :: Property+hprop_sortNubCorrect = property $ do+ xs <- forAll genIntList+ U.sortNub xs === (U.sort $ nub xs)++hprop_unstableNubCorrect :: Property+hprop_unstableNubCorrect = property $ do+ xs <- forAll genIntList+ (U.sort $ U.unstableNub xs) === (U.sort $ nub xs)
− test/Test/Universum/Property.hs
@@ -1,177 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE TypeFamilies #-}--module Test.Universum.Property- ( hedgehogTestTree- ) where--import Universum--import Data.List (nub)-import Hedgehog (Gen, MonadGen, Property, assert, forAll, property, (===))-#if MIN_VERSION_hedgehog(1,0,0)-import Hedgehog (GenBase)-#endif-import Test.Tasty (TestTree, testGroup)-import Test.Tasty.Hedgehog--import qualified Data.ByteString as B-import qualified Data.ByteString.Lazy as LB-import qualified Data.Text as T-import qualified Data.Text.Lazy as LT-import qualified Hedgehog.Gen as Gen-import qualified Hedgehog.Range as Range-import qualified Universum as U--hedgehogTestTree :: TestTree-hedgehogTestTree = testGroup "Tests" [stringProps, utfProps, listProps, boolMProps]--stringProps :: TestTree-stringProps = testGroup "String conversions"- [ testProperty "toString . toText = id" prop_StringToTextAndBack- , testProperty "`toString . toText` for UTF-16 surrogate"- prop_StringToTextAndBackSurrogate- , testProperty "toText . toString = id" prop_TextToStringAndBack- ]--utfProps :: TestTree-utfProps = testGroup "utf8 conversion property tests"- [ testProperty "String to ByteString invertible" prop_StringToBytes- , testProperty "Text to ByteString invertible" prop_TextToBytes- , testProperty "ByteString to Text or String invertible" prop_BytesTo- ]--#if MIN_VERSION_hedgehog(1,0,0)-unicode' :: (MonadGen m, GenBase m ~ Identity) => m U.Char-#else-unicode' :: MonadGen m => m U.Char-#endif-unicode' = do- a <- Gen.unicode- if U.elem a ['\65534', '\65535']- then unicode'- else return a--utf8String :: Gen U.String-utf8String = Gen.string (Range.linear 0 10000) unicode'--unicodeAllString :: Gen U.String-unicodeAllString = Gen.string (Range.linear 0 10000) Gen.unicodeAll--utf8Text :: Gen T.Text-utf8Text = Gen.text (Range.linear 0 10000) unicode'--unicodeAllText :: Gen T.Text-unicodeAllText = Gen.text (Range.linear 0 10000) Gen.unicodeAll--utf8Bytes :: Gen B.ByteString-utf8Bytes = Gen.utf8 (Range.linear 0 10000) unicode'---- "\65534" fails, but this is from BU.toString--- > import qualified Data.ByteString.UTF8 as BU--- > BU.toString (BU.fromString "\65534") == "\65533"--- > True--prop_StringToTextAndBack :: Property-prop_StringToTextAndBack = property $ do- str <- forAll unicodeAllString- toString (toText str) === str---- | See comment to this function:--- <http://hackage.haskell.org/package/text-1.2.3.1/docs/src/Data.Text.Internal.html#safe>------ While 'String' may contain surrogate UTF-16 code points, actually UTF-8--- doesn't allow them, as well as 'Text'. 'Data.Text.pack' replaces invalid--- characters with unicode replacement character, so by default--- @toString . toText@ is not identity.------ However, we have a rewrite rule by which we /replace/ @toString . toText@--- occurrences with the identity function.-prop_StringToTextAndBackSurrogate :: Property-prop_StringToTextAndBackSurrogate = property $ do- -- Surrogate character like this one should remain intact- -- Without rewrite rule this string would be transformed to "\9435"- let str = "\xD800"- toString (toText str) === str--prop_TextToStringAndBack :: Property-prop_TextToStringAndBack = property $ do- txt <- forAll unicodeAllText- toText (toString txt) === txt--prop_StringToBytes :: Property-prop_StringToBytes = property $ do- str <- forAll utf8String- assert $ str == (decodeUtf8 (encodeUtf8 str :: B.ByteString))- && str == (decodeUtf8 (encodeUtf8 str :: LB.ByteString))---prop_TextToBytes :: Property-prop_TextToBytes = property $ do- txt <- forAll utf8Text- assert $ txt == (decodeUtf8 (encodeUtf8 txt :: B.ByteString))- && txt == (decodeUtf8 (encodeUtf8 txt :: LB.ByteString))---- "\239\191\190" fails, but this is the same as "\65534" :: String-prop_BytesTo :: Property-prop_BytesTo = property $ do- utf <- forAll utf8Bytes- assert $ utf == (encodeUtf8 (decodeUtf8 utf :: U.String))- && utf == (encodeUtf8 (decodeUtf8 utf :: T.Text))- && utf == (encodeUtf8 (decodeUtf8 utf :: LT.Text))---- ordNub--listProps :: TestTree-listProps = testGroup "list function property tests"- [ testProperty "Hedgehog ordNub xs == nub xs" prop_ordNubCorrect- , testProperty "Hedgehog hashNub xs == nub xs" prop_hashNubCorrect- , testProperty "Hedgehog sortNub xs == sort $ nub xs" prop_sortNubCorrect- , testProperty "Hedgehog sort $ unstableNub xs == sort $ nub xs" prop_unstableNubCorrect- ]--genIntList :: Gen [U.Int]-genIntList = Gen.list (Range.linear 0 10000) Gen.enumBounded--prop_ordNubCorrect :: Property-prop_ordNubCorrect = property $ do- xs <- forAll genIntList- U.ordNub xs === nub xs--prop_hashNubCorrect :: Property-prop_hashNubCorrect = property $ do- xs <- forAll genIntList- U.hashNub xs === nub xs--prop_sortNubCorrect :: Property-prop_sortNubCorrect = property $ do- xs <- forAll genIntList- U.sortNub xs === (U.sort $ nub xs)--prop_unstableNubCorrect :: Property-prop_unstableNubCorrect = property $ do- xs <- forAll genIntList- (U.sort $ U.unstableNub xs) === (U.sort $ nub xs)----- logicM--- this section needs a little more thought--genBoolList :: Gen [U.Bool]-genBoolList = Gen.list (Range.linear 0 1000) Gen.bool--boolMProps :: TestTree-boolMProps = testGroup "lifted logic function property tests"- [ testProperty "Hedgehog andM" prop_andM- , testProperty "Hedgehog orM" prop_orM- ]--prop_andM :: Property-prop_andM = property $ do- bs <- forAll genBoolList- U.andM (return <$> bs) === ((return $ U.and bs) :: U.Maybe U.Bool)--prop_orM :: Property-prop_orM = property $ do- bs <- forAll genBoolList- U.orM (return <$> bs) === ((return $ U.or bs) :: U.Maybe U.Bool)
+ test/Test/Universum/StringProps.hs view
@@ -0,0 +1,55 @@+-- Some tests in this module have a caveat: they depend on compiler+-- optimizations and will likely fail if compiled with -O0.+-- That's because they depend on rewrite rules (and test these rules),+-- and these rules are usually not triggered without certain optimizations.++module Test.Universum.StringProps+ ( hprop_StringToTextAndBack+ , hprop_StringToTextAndBackSurrogate+ , hprop_TextToStringAndBack+ ) where++import Universum++import qualified Data.Text as T+import Hedgehog (Gen, Property, forAll, property, (===))+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range+import qualified Universum as U++unicodeAllString :: Gen U.String+unicodeAllString = Gen.string (Range.linear 0 10000) Gen.unicodeAll++unicodeAllText :: Gen T.Text+unicodeAllText = Gen.text (Range.linear 0 10000) Gen.unicodeAll++-- "\65534" fails, but this is from BU.toString+-- > import qualified Data.ByteString.UTF8 as BU+-- > BU.toString (BU.fromString "\65534") == "\65533"+-- > True++hprop_StringToTextAndBack :: Property+hprop_StringToTextAndBack = property $ do+ str <- forAll unicodeAllString+ toString (toText str) === str++-- |+-- While 'String' may contain surrogate UTF-16 code points, actually UTF-8+-- doesn't allow them, as well as 'Text'. 'Data.Text.pack' replaces invalid+-- characters with unicode replacement character, so by default+-- @toString . toText@ is not identity.+--+-- However, we have a rewrite rule by which we /replace/ @toString . toText@+-- occurrences with the identity function.+hprop_StringToTextAndBackSurrogate :: Property+hprop_StringToTextAndBackSurrogate = property $ do+ -- Surrogate character like this one should remain intact+ -- Without the rewrite rule this string would be transformed to some other,+ -- valid string+ let str = "\xD800"+ toString (toText str) === str++hprop_TextToStringAndBack :: Property+hprop_TextToStringAndBack = property $ do+ txt <- forAll unicodeAllText+ toText (toString txt) === txt
+ test/Test/Universum/UtfProps.hs view
@@ -0,0 +1,64 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE TypeFamilies #-}++module Test.Universum.UtfProps+ ( hprop_StringToBytes+ , hprop_TextToBytes+ , hprop_BytesTo+ ) where++import Universum++import Hedgehog (Gen, MonadGen, Property, assert, forAll, property)+#if MIN_VERSION_hedgehog(1,0,0)+import Hedgehog (GenBase)+#endif++import qualified Data.ByteString as B+import qualified Data.ByteString.Lazy as LB+import qualified Data.Text as T+import qualified Data.Text.Lazy as LT+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range+import qualified Universum as U++#if MIN_VERSION_hedgehog(1,0,0)+unicode' :: (MonadGen m, GenBase m ~ Identity) => m U.Char+#else+unicode' :: MonadGen m => m U.Char+#endif+unicode' = do+ a <- Gen.unicode+ if U.elem a ['\65534', '\65535']+ then unicode'+ else return a++utf8String :: Gen U.String+utf8String = Gen.string (Range.linear 0 10000) unicode'++utf8Text :: Gen T.Text+utf8Text = Gen.text (Range.linear 0 10000) unicode'++utf8Bytes :: Gen B.ByteString+utf8Bytes = Gen.utf8 (Range.linear 0 10000) unicode'++hprop_StringToBytes :: Property+hprop_StringToBytes = property $ do+ str <- forAll utf8String+ assert $ str == (decodeUtf8 (encodeUtf8 str :: B.ByteString))+ && str == (decodeUtf8 (encodeUtf8 str :: LB.ByteString))+++hprop_TextToBytes :: Property+hprop_TextToBytes = property $ do+ txt <- forAll utf8Text+ assert $ txt == (decodeUtf8 (encodeUtf8 txt :: B.ByteString))+ && txt == (decodeUtf8 (encodeUtf8 txt :: LB.ByteString))++-- "\239\191\190" fails, but this is the same as "\65534" :: String+hprop_BytesTo :: Property+hprop_BytesTo = property $ do+ utf <- forAll utf8Bytes+ assert $ utf == (encodeUtf8 (decodeUtf8 utf :: U.String))+ && utf == (encodeUtf8 (decodeUtf8 utf :: T.Text))+ && utf == (encodeUtf8 (decodeUtf8 utf :: LT.Text))
+ test/Tree.hs view
@@ -0,0 +1,1 @@+{-# OPTIONS_GHC -F -pgmF tasty-discover -optF --tree-display -optF --generated-module -optF Tree #-}
universum.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.2 name: universum-version: 1.7.3+version: 1.8.3.1 synopsis: Custom prelude used in Serokell description: See README.md file for more details. homepage: https://github.com/serokell/universum@@ -13,18 +13,22 @@ stability: stable build-type: Simple bug-reports: https://github.com/serokell/universum/issues-tested-with: GHC == 8.4.4- , GHC == 8.6.5- , GHC == 8.8.4- , GHC == 8.10.7- , GHC == 9.0.1+tested-with: GHC == 8.10.7+ , GHC == 9.0.2+ , GHC == 9.2.8+ , GHC == 9.4.8+ , GHC == 9.6.7+ , GHC == 9.8.4+ , GHC == 9.10.3+ , GHC == 9.12.2+ , GHC == 9.14.1 extra-doc-files: CHANGES.md , CONTRIBUTING.md , README.md source-repository head type: git- location: git@github.com:serokell/universum.git+ location: https://github.com/serokell/universum.git common common-options build-depends: base >= 4.8 && < 5@@ -40,12 +44,18 @@ -Wno-missing-local-signatures -Wno-monomorphism-restriction -Wno-implicit-prelude- if impl(ghc >= 8.10.1)- ghc-options: -Wno-prepositive-qualified-module+ -Wno-prepositive-qualified-module -Wno-inferred-safe-imports+ if impl(ghc >= 9.2.0)+ ghc-options: -Wno-missing-kind-signatures + if impl(ghc >= 9.14.0)+ ghc-options: -Wno-pattern-namespace-specifier+ default-language: Haskell2010 + default-extensions: TypeOperators+ library import: common-options hs-source-dirs: src@@ -94,16 +104,13 @@ build-depends: bytestring , containers , deepseq- , ghc-prim >= 0.4.0.0 , hashable , microlens , microlens-mtl , mtl , safe-exceptions , stm- -- Make sure that "toString-toText-rewritting" note- -- is still valid when bumping this constraint.- , text >= 1.0.0.0 && <= 1.2.5.0+ , text >= 1.0.0.0 && <= 2.2 , transformers , unordered-containers , utf8-string@@ -119,18 +126,24 @@ hs-source-dirs: test main-is: Spec.hs - other-modules: Test.Universum.Property+ other-modules:+ Tree+ Test.Universum.Issue208+ Test.Universum.StringProps+ Test.Universum.UtfProps+ Test.Universum.ListProps+ Test.Universum.BoolMProps build-depends: universum , bytestring , text , hedgehog , tasty- , tasty-hedgehog < 1.2.0.0-- if impl(ghc >= 8.10.1)- ghc-options: -Wno-missing-safe-haskell-mode+ , tasty-hedgehog+ build-tool-depends:+ tasty-discover:tasty-discover + ghc-options: -Wno-missing-safe-haskell-mode ghc-options: -threaded test-suite universum-doctest@@ -145,10 +158,12 @@ build-depends: doctest , Glob - if impl(ghc >= 8.10.1)- ghc-options: -Wno-missing-safe-haskell-mode-+ ghc-options: -Wno-missing-safe-haskell-mode ghc-options: -threaded+ -- https://github.com/sol/doctest/issues/327+ -- TODO: re-enable when the issue is resolved+ if impl(ghc >= 9.0.0)+ buildable: False benchmark universum-benchmark import: common-options@@ -163,8 +178,11 @@ , text , unordered-containers - if impl(ghc >= 8.10.1)- ghc-options: -Wno-missing-safe-haskell-mode+ ghc-options: -Wno-missing-safe-haskell-mode+ if impl(ghc >= 9.8.0)+ ghc-options: -Wno-x-partial+ -- TODO (#298): migrate from gauge to something+ buildable: False default-extensions: NoImplicitPrelude ScopedTypeVariables