universum 1.1.0 → 1.1.1
raw patch · 26 files changed
+397/−112 lines, 26 filesdep +gaugedep −criteriondep ~semigroups
Dependencies added: gauge
Dependencies removed: criterion
Dependency ranges changed: semigroups
Files
- CHANGES.md +14/−0
- CONTRIBUTING.md +46/−0
- README.md +102/−43
- benchmark/Main.hs +15/−23
- src/Universum.hs +57/−9
- src/Universum/Bool/Guard.hs +2/−0
- src/Universum/Bool/Reexport.hs +2/−0
- src/Universum/Container/Class.hs +53/−9
- src/Universum/Debug.hs +3/−0
- src/Universum/DeepSeq.hs +4/−0
- src/Universum/Function.hs +2/−0
- src/Universum/Functor/Fmap.hs +17/−1
- src/Universum/Functor/Reexport.hs +2/−0
- src/Universum/Lifted/ST.hs +2/−0
- src/Universum/List/Reexport.hs +3/−1
- src/Universum/List/Safe.hs +12/−3
- src/Universum/Monad/Container.hs +3/−0
- src/Universum/Monad/Maybe.hs +11/−5
- src/Universum/Monad/Reexport.hs +2/−0
- src/Universum/Monoid.hs +4/−7
- src/Universum/Nub.hs +18/−1
- src/Universum/String/Conversion.hs +6/−0
- src/Universum/String/Reexport.hs +2/−0
- src/Universum/Unsafe.hs +5/−2
- src/Universum/VarArg.hs +1/−0
- universum.cabal +9/−8
CHANGES.md view
@@ -1,3 +1,17 @@+1.1.1+=====++* [#148](https://github.com/serokell/universum/issues/148):+ Add `CODEOWNERS` and contributing guide.+* [#135](https://github.com/serokell/universum/issues/135):+ Add documentation regarding internal module structure.+* [#113](https://github.com/serokell/universum/issues/113):+ Annotate `at` function from `Unsafe` module and `ordNub`+ function from `Nub` module with `liquidhaskell`.+* [#73](https://github.com/serokell/universum/issues/73):+ Add more examples to docs and fix warnings where possible.+* Move reexport of `NonEmpty` to `Universum.List` module.+ 1.1.0 =====
+ CONTRIBUTING.md view
@@ -0,0 +1,46 @@+# Contributing to `universum`++## :wave: Greetings Traveler!++I'm glad you're reading this, I really appreciate the effort you're+putting in. Thank you for your help in making this library awesome! :sparkles:++### How to contribute++#### Report bugs or feature request+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/serokell/universum/issues/new) in free format.++#### 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 exist 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!++To get started with this you should first fork, then clone the repo:++ git clone git@github.com:your-username/universum.git++Make your changes and consider the following check list to go through before submitting your pull request.++#### :white_check_mark: Check list+- [ ] Project compiles+- [ ] New/fixed features work as expected+- [ ] Old features do not break after the change+- [ ] _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`++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:++[pr]: https://github.com/serokell/universum/compare/
README.md view
@@ -8,11 +8,21 @@ [](http://stackage.org/nightly/package/universum) [](https://opensource.org/licenses/MIT) -A custom prelude used in Serokell.+`universum` is a custom prelude used in @Serokell that has: -What is this?--------------+1. **Excellent documentation**: tutorial, migration guide from `Prelude`,+ Haddock with examples for (almost) every function,+ all examples are tested with [`doctest`](http://hackage.haskell.org/package/doctest),+ documenation regarding internal module structure.+2. `universum`-specific [HLint](http://hackage.haskell.org/package/hlint) rules:+ [`.hlint.yaml`](https://github.com/serokell/universum/blob/master/.hlint.yaml)+3. Only a few LiquidHaskell properties right now, but LiquidHaskell is on Travis+ CI and other properties are just waiting to be added!+4. Focus on safety, convenience and efficiency. +What is this file about?+------------------------+ This README contains introduction to `Universum` and a tutorial on how to use it. Structure of this tutorial@@ -20,38 +30,38 @@ This tutorial has several parts: -1. Philosophy and motivation.-2. How to use `universum`.-3. Changes in `Prelude` (some gotchas).-4. Already known things that weren't in `Prelude` brought into scope.-5. New things added.+1. [Philosophy and motivation.](#why-another-custom-prelude-)+2. [How to use `universum`.](#how-to-use-universum-)+3. [Changes in `Prelude` (some gotchas).](#gotchas-)+4. [Already known things that weren't in `Prelude` brought into scope.](#things-that-you-were-already-using-but-now-you-dont-have-to-import-them-explicitly-)+5. [New things added.](#whats-new-)+6. [Migration guide from `Prelude`.](#migration-guide-from-prelude-) -This is not a tutorial on _Haskell_, and not even a tutorial on each function. For the detailed-documentation of every function with examples and usages see+This is neither a tutorial on _Haskell_ nor tutorial on each function contained in Universum. For detailed+documentation of every function together with examples and usage, see [_Haddock documentation_](http://hackage.haskell.org/package/universum). -Why another custom Prelude?+Why another custom Prelude? [↑](#structure-of-this-tutorial) --------------------------- ### Motivation -In [Serokell](https://github.com/serokell/), we want to be as much productive as possible.-That's why we are using [_Haskell_](https://haskell-lang.org/). This choice of language implies+At [Serokell](https://github.com/serokell/), we strive to be as productive as possible. That's why we are using [_Haskell_](https://haskell-lang.org/). This choice of language implies that we're restricted to use [`Prelude`](http://hackage.haskell.org/package/base-4.9.1.0/docs/Prelude.html):-implicit import of basic functions, type classes and data types. But the default `Prelude`+implicit import of basic functions, type classes and data types. Unfortunately, the default `Prelude` [is considered to be not so good](https://news.ycombinator.com/item?id=8002749) due to some historical reasons. -This is why we decided to use a better tool. Hopefully _Haskell_ provides us with ability-to replace default `Prelude` with some alternative. All we need to do is to implement-new basic set of defaults. But we don't intend to implement everything from scratch.-There're already plenty of [preludes](https://guide.aelve.com/haskell/alternative-preludes-zr69k1hc).-After some hot long discussions our team decided to base our custom prelude on+This is why we decided to use a better tool. Luckily, _Haskell_ provides us with the ability+to replace default `Prelude` with an alternative. All we had to do is to implement a+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). -The next section explains why we have 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 custom `Prelude`.+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`. ### Main goals @@ -59,18 +69,17 @@ 1. Avoid all [partial functions](https://www.reddit.com/r/haskell/comments/5n51u3/why_are_partial_functions_as_in_head_tail_bad/). We like [total](http://mathworld.wolfram.com/TotalFunction.html) and exception-free functions.- Though you can still use some unsafe functions from `Universum.Unsafe` module+ You can still use some unsafe functions from `Universum.Unsafe` module, but they are not exported by default. 2. Use more efficient [string representations](https://www.reddit.com/r/haskell/comments/29jw0s/whats_wrong_with_string/). `String` type is crushingly inefficient. All our functions either try to be polymorphic over string- types, or use [`Text`](http://hackage.haskell.org/package/text-1.2.2.1/docs/Data-Text.html)- as the default string type. `String` type alias is still reexported, because the community- is evolving slowly, some libraries still use `String` type. But we recommend to avoid `String`!-3. Don't reinvent the wheel. We're not trying to rebuild whole type hierarchy from scratch,+ type or use [`Text`](http://hackage.haskell.org/package/text-1.2.2.1/docs/Data-Text.html)+ as the default string type. Because the community is evolving slowly, some libraries still use `String` type, so `String` type alias is still reexported. We recommend to avoid `String` as much as you can!+3. Try to not reinvent the wheel. We're not trying to rebuild whole type hierarchy from scratch, as it's done in [`classy-prelude`](https://github.com/snoyberg/mono-traversable). Instead, we reexport common and well-known things from `base` and some other- libraries used in everyday production programming in _Haskell_.- > **Note**: well, we did end up inventing something new.+ 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) Things like `liftIO`, `ReaderT` type, `MVar`-related functions have unambiguous names,@@ -86,8 +95,8 @@ 3. Trying to make writing production code easier (see [enhancements and fixes](https://github.com/serokell/universum/issues)). -How to use Universum-----------+How to use Universum [↑](#structure-of-this-tutorial)+-------------------- Okay, enough philosophy. If you want to just start using `universum` and explore it with the help of compiler, set everything up according to the instructions below.@@ -110,12 +119,17 @@ import Universum ``` -If you're using [Emacs](https://www.gnu.org/software/emacs/), you can+If you're using [Emacs](https://www.gnu.org/software/emacs/) and don't want to+type `import Universum` manually every time, you can [modify your configs](https://github.com/serokell/universum/issues/8#issuecomment-276444879)-a little bit if you don't want to type `import Universum` manually every time.+a little bit. +If you want to get familiar with `universum` internal structure, you can just+read top-level documentation for+[`Universum`](http://hackage.haskell.org/package/universum/docs/Universum.html)+module. -Gotchas+Gotchas [↑](#structure-of-this-tutorial) ------- * `head`, `tail`, `last`, `init` work with `NonEmpty a` instead of `[a]`.@@ -148,8 +162,8 @@ * `error` takes `Text`. -Things that you were already using, but now you don't have to import them explicitly---------------------------------------------------------------------------+Things that you were already using, but now you don't have to import them explicitly [↑](#structure-of-this-tutorial)+------------------------------------------------------------------------------------ ### Commonly used libraries @@ -194,7 +208,7 @@ module explicitly. Instead use functionality from `safe-exceptions` provided by `universum` or import `Control.Exceptions.Safe` module. -What's new?+What's new? [↑](#structure-of-this-tutorial) ----------- Finally, we can move to part describing the new cool features we bring with `universum`.@@ -281,7 +295,58 @@ `evaluate` and `evaluate . force`. * `ToPairs` type class for data types that can be converted to list of pairs (like `Map` or `HashMap` or `IntMap`). -Projects that use Universum+Migration guide from Prelude [↑](#structure-of-this-tutorial)+----------------------------++In order to replace default `Prelude` with `universum` you should start with instructions given in+[how to use universum](https://github.com/serokell/universum#how-to-use-universum-) section.++This section describes what you need to change to make your code compile with `universum`.++1. Enable `-XOverloadedStrings` and `-XTypeFamilies` extension by default for your project.+2. Since `head`, `tail`, `last` and `init` work for `NonEmpty` you should+ refactor your code in one of the multiple ways described below:+ 1. Change `[a]` to `NonEmpty a` where it makes sense.+ 2. Use functions which return `Maybe`. They can be implemented using `nonEmpty` function. Like `head <$> nonEmpty l`.+ + `head <$> nonEmpty l` is `safeHead l`+ + `tail` is `drop 1`. It's almost never a good idea to use `tail` from `Prelude`.+ 3. Add `import qualified Universum.Unsafe as Unsafe` and replace function with qualified usage.+3. If you use `fromJust` or `!!` you should use them from `import qualified Universum.Unsafe as Unsafe`.+4. Derive or implement `Container` instances for your data types which implement+ `Foldable` instances. This can be done in a single line because `Container`+ type class automatically derives from `Foldable`.+5. `Container` type class from `universum` replaces `Foldable` and doesn't have+ instances for `Maybe a`, `(a, b)`, `Identity a` and `Either a b`. If you use+ `foldr` or `forM_` or similar for something like `Maybe a` you should replace+ usages of such function with monomorhpic alternatives:+ * `Maybe`+ + `(?:) :: Maybe a -> a -> a`+ + `fromMaybe :: a -> Maybe a -> a`+ + `maybeToList :: Maybe a -> [a]`+ + `maybeToMonoid :: Monoid m => Maybe m -> m`+ + `maybe :: b -> (a -> b) -> Maybe a -> b`+ + `whenJust :: Applicative f => Maybe a -> (a -> f ()) -> f ()`+ + `whenJustM :: Monad m => m (Maybe a) -> (a -> m ()) -> m ()`++ * `Either`+ + `fromLeft :: a -> Either a b -> a`+ + `fromRight :: b -> Either a b -> b`+ + `either :: (a -> c) -> (b -> c) -> Either a b -> c`+ + `whenRight :: Applicative f => Either l r -> (r -> f ()) -> f ()`+ + `whenRightM :: Monad m => m (Either l r) -> (r -> m ()) -> m ()`++6. If you have types like `foo :: Foldable f => f a -> a -> a` you should chose one of the following:+ + `Right`: Modify types for `Container` like `foo :: (Container t, Element t ~ a) => t -> a -> a`.+ + `Left`: Import `Data.Foldable` module `qualified` and use everything `Foldable`-related qualified.+7. Forget about `String` type.+ + Replace `putStr` and `putStrLn` with `putText` and `putTextLn`.+ + Replace `(++)` with `(<>)` for `String`-like types.+ + Try to use [`fmt`](http://hackage.haskell.org/package/fmt) library if you need to construct messages.+ + Use `toText/toLText/toString` functions to convert to `Text/LazyText/String` types.+ + Use `encodeUtf8/decodeUtf8` to convert to/from `ByteString`.+8. Run `hlint` using `.hlint.yaml` file from `universum` package to cleanup code and imports.++Projects that use Universum [↑](#structure-of-this-tutorial) --------------------------- - [cardano-report-server](https://github.com/input-output-hk/cardano-report-server)@@ -289,9 +354,3 @@ - [importify](https://github.com/serokell/importify) - [log-warper](https://github.com/serokell/log-warper) - [orgstat](https://github.com/volhovm/orgstat)--License----------Released under the MIT License.-Copyright (c) 2016, Stephen Diehl, 2016-2017, Serokell
benchmark/Main.hs view
@@ -1,26 +1,18 @@-{-# LANGUAGE ExplicitForAll #-}-{-# LANGUAGE ScopedTypeVariables #-}- module Main where -import Control.DeepSeq (NFData)-import Control.Monad.Identity (Identity (..))-import Criterion.Main (Benchmark, bench, bgroup, defaultMain, nf, whnf)-import Data.Hashable (Hashable)-import Data.List (group, head, nub, sort, zip5)-import Data.Text (Text)+import Universum hiding (show) -import Universum.Container (flipfoldl', foldl')-import Universum.Monad (concatMapM)-import Universum.Nub (hashNub, ordNub, sortNub, unstableNub)-import Universum.VarArg ((...))+import Data.List (nub, zip5)+import Gauge (Benchmark, bench, bgroup, nf, whnf)+import Gauge.Main (defaultMain)+import Prelude (show) import qualified Data.Foldable as Foldable (elem) import qualified Data.HashSet as HashSet (fromList, insert)-import qualified Data.List.NonEmpty as NonEmpty+import qualified Data.List.NonEmpty as NonEmpty (group, head) import qualified Data.Set as Set (fromList)-import qualified Data.Text as T import qualified Universum.Container as Container (elem)+import qualified Universum.Unsafe as Unsafe main :: IO () main = defaultMain@@ -76,7 +68,7 @@ ] groupSort :: [a] -> [a]- groupSort = map head . group . sort+ groupSort = map Unsafe.head . group . sort safeSort :: [a] -> [a] safeSort = map NonEmpty.head . NonEmpty.group . sort@@ -91,7 +83,7 @@ allStrings ch = [ c : s | s <- "" : allStrings ch, c <- ['a'..ch] ] nStrings :: Char -> Int -> [Text]-nStrings ch n = take n $ map T.pack $ allStrings ch+nStrings ch n = take n $ map toText $ allStrings ch bgroupSuperComposition :: Benchmark bgroupSuperComposition = bgroup "(...)"@@ -115,14 +107,14 @@ ] where super10 = null- ... (: []) ... head ... pure ... head- ... (: [(), (), (), ()]) ... head ... (: []) ... head- ... (: [()]) ... head ... (: [(), ()]) ... head+ ... (: []) ... Unsafe.head ... pure ... Unsafe.head+ ... (: [(), (), (), ()]) ... Unsafe.head ... (: []) ... Unsafe.head+ ... (: [()]) ... Unsafe.head ... (: [(), ()]) ... Unsafe.head norm10 = null- . (: []) . head . pure . head- . (: [(), (), (), ()]) . head . (: []) . head- . (: [()]) . head . (: [(), ()]) . head+ . (: []) . Unsafe.head . pure . Unsafe.head+ . (: [(), (), (), ()]) . Unsafe.head . (: []) . Unsafe.head+ . (: [()]) . Unsafe.head . (: [(), ()]) . Unsafe.head super5arg :: [()] -> [()] -> [()] -> [()] -> [()] -> Bool super5arg = super10 ... map fst5 ... zip5
src/Universum.hs view
@@ -1,14 +1,62 @@ {-# LANGUAGE Trustworthy #-} --- | Main module that reexports all functionality allowed to use--- without importing any other modules. Just add next lines to your--- module to replace default ugly 'Prelude' with better one.------ @--- {-\# LANGUAGE NoImplicitPrelude \#-}------ import Universum--- @+{- | Main module that reexports all functionality allowed to use+without importing any other modules. Just add next lines to your+module to replace default 'Prelude' with better one.++@+\{\-\# LANGUAGE NoImplicitPrelude \#\-\}++__import__ "Universum"+@++This documentation section contains description of internal module structure to+help navigate between modules, search for interesting functionalities and+understand where you need to put your new changes.++Functions and types are distributed across multiple modules and grouped by+meaning or __theme__. Name of the module should give you hints regarding what+this module contains. Some /themes/ contain a great amount of both reexported+functions and functions of our own. To make it easier to understand these huge+chunks of functions, all reexported stuff is moved into separate module with+name @Universum.SomeTheme.Reexport@ and our own functions and types are in+@Universum.SomeTheme.SomeName@. For example, see modules+"Universum.Container.Class" and "Universum.Container.Reexport".++Below is a short description of what you can find under different modules:++* __"Universum.Applicative"__: reexports from "Control.Applicative" and some+ general-purpose applicative combinators.+* __"Universum.Base"__: different general types and type classes from @base@+ package ('Int', 'Num', 'Generic', etc.) not exported by other modules.+* __"Universum.Bool"__: 'Bool' data type with different predicates and combinators.+* __"Universum.Container"__: 'Foldable' replacement, types from @containers@+ and @unordered-containers@ and @vector@ packages.+* __"Universum.Debug"__: @trace@-like debugging functions with compile-time+ warnings (so you don't forget to remove them)+* __"Universum.DeepSeq"__: reexports from "Control.DeepSeq" module and+ functions to evaluate expressions to weak-head normal form or normal form.+* __"Universum.Exception"__: reexports "Control.Exception.Safe" from+ @safe-exceptions@ package, 'bug' as better 'error', 'Exc' pattern synonym for+ convenient pattern-matching on exceptions.+* __"Universum.Function"__: almost everything from "Data.Function" module.+* __"Universum.Functor"__: reexports from "Data.Functor", "Data.Bifunctor",+ other useful 'Functor' combinators.+* __"Universum.Lifted"__: lifted to 'MonadIO' functions to work with console,+ files, 'IORef's, 'MVar's, etc.+* __"Universum.List"__: big chunk of "Data.List", 'NonEmpty' type and+ functions for this type ('head', 'tail', 'last', 'init').+* __"Universum.Monad"__: monad transormers, combinators for 'Maybe' and 'Either'.+* __"Universum.Monoid"__: reexports from "Data.Monoid" and "Data.Semigroup".+* __"Universum.Nub"__: better versions of @nub@ function for list.+* __"Universum.Print"__: polymorphic 'putStrLn' function and functions to print 'Text'.+* __"Universum.String"__: reexports from @text@ and @bytestring@ packages with+ conversion functions between different textual types.+* __"Universum.TypeOps"__: convenient and fancy type-level operators.+* __"Universum.Unsafe"__: unsafe functions (produce 'error').+ Not exported by "Universum" module by default.+* __"Universum.VarArg"__: variadic composition operator '...'.+-} module Universum ( -- * Reexports from base and from modules in this repo
src/Universum/Bool/Guard.hs view
@@ -1,3 +1,5 @@+-- | This module contains monadic predicates.+ module Universum.Bool.Guard ( guardM , ifM
src/Universum/Bool/Reexport.hs view
@@ -1,3 +1,5 @@+-- | This module reexports functions to work with 'Bool' type.+ module Universum.Bool.Reexport ( module Control.Monad , module Data.Bool
src/Universum/Container/Class.hs view
@@ -42,7 +42,7 @@ ) where import Data.Coerce (Coercible, coerce)-import Prelude hiding (all, and, any, elem, foldMap, foldl, foldr, mapM_, notElem, null, or,+import Prelude hiding (all, and, any, elem, foldMap, foldl, foldr, mapM_, notElem, null, or, print, product, sequence_, sum) import Universum.Applicative (Alternative (..), Const, ZipList, pass)@@ -60,7 +60,7 @@ #if ( __GLASGOW_HASKELL__ >= 800 ) import qualified Data.List.NonEmpty as NE-import Universum.Monoid (NonEmpty)+import Universum.List.Reexport (NonEmpty) #endif import qualified Data.Foldable as Foldable@@ -86,6 +86,9 @@ import qualified Data.Vector.Unboxed as VU -- $setup+-- >>> import Universum.Base (even)+-- >>> import Universum.Bool (when)+-- >>> import Universum.Print (print, putTextLn) -- >>> import Universum.String (Text) -- >>> import qualified Data.HashMap.Strict as HashMap @@ -604,45 +607,86 @@ product :: (Container t, Num (Element t)) => t -> Element t product = foldl' (*) 1 --- | Constrained to 'Container' version of 'Data.Foldable.traverse_'.+{- | Constrained to 'Container' version of 'Data.Foldable.traverse_'.++>>> traverse_ putTextLn ["foo", "bar"]+foo+bar++-} traverse_ :: (Container t, Applicative f) => (Element t -> f b) -> t -> f () traverse_ f = foldr ((*>) . f) pass --- | Constrained to 'Container' version of 'Data.Foldable.for_'.+{- | Constrained to 'Container' version of 'Data.Foldable.for_'.++>>> for_ [1 .. 5 :: Int] $ \i -> when (even i) (print i)+2+4++-} for_ :: (Container t, Applicative f) => t -> (Element t -> f b) -> f () for_ = flip traverse_ {-# INLINE for_ #-} --- | Constrained to 'Container' version of 'Data.Foldable.mapM_'.+{- | Constrained to 'Container' version of 'Data.Foldable.mapM_'.++>>> mapM_ print [True, False]+True+False++-} mapM_ :: (Container t, Monad m) => (Element t -> m b) -> t -> m () mapM_ f= foldr ((>>) . f) pass --- | Constrained to 'Container' version of 'Data.Foldable.forM_'.+{- | Constrained to 'Container' version of 'Data.Foldable.forM_'.++>>> forM_ [True, False] print+True+False++-} forM_ :: (Container t, Monad m) => t -> (Element t -> m b) -> m () forM_ = flip mapM_ {-# INLINE forM_ #-} --- | Constrained to 'Container' version of 'Data.Foldable.sequenceA_'.+{- | Constrained to 'Container' version of 'Data.Foldable.sequenceA_'.++>>> sequenceA_ [putTextLn "foo", print True]+foo+True++-} sequenceA_ :: (Container t, Applicative f, Element t ~ f a) => t -> f () sequenceA_ = foldr (*>) pass --- | Constrained to 'Container' version of 'Data.Foldable.sequence_'.+{- | Constrained to 'Container' version of 'Data.Foldable.sequence_'.++>>> sequence_ [putTextLn "foo", print True]+foo+True++-} sequence_ :: (Container t, Monad m, Element t ~ m a) => t -> m () sequence_ = foldr (>>) pass --- | Constrained to 'Container' version of 'Data.Foldable.asum'.+{- | Constrained to 'Container' version of 'Data.Foldable.asum'.++>>> asum [Nothing, Just [False, True], Nothing, Just [True]]+Just [False,True]++-} asum :: (Container t, Alternative f, Element t ~ f a) => t -> f a
src/Universum/Debug.hs view
@@ -5,6 +5,9 @@ {-# LANGUAGE PolyKinds #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE Trustworthy #-}+#if ( __GLASGOW_HASKELL__ >= 804 )+{-# LANGUAGE TypeInType #-}+#endif -- | 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/DeepSeq.hs view
@@ -1,3 +1,7 @@+-- | This module contains useful functions to evaluate expressions to weak-head+-- normal form or just normal form. Useful to force traces or @error@ inside+-- monadic computation or to remove space leaks.+ module Universum.DeepSeq ( module Control.DeepSeq , evaluateNF
src/Universum/Function.hs view
@@ -1,3 +1,5 @@+-- | This module reexports very basic and primitive functions and function combinators.+ module Universum.Function ( module Data.Function , identity
src/Universum/Functor/Fmap.hs view
@@ -1,5 +1,7 @@ {-# LANGUAGE Safe #-} +-- | This module contains useful functions to work with 'Functor' type class.+ module Universum.Functor.Fmap ( map , (<<$>>)@@ -8,7 +10,21 @@ import Universum.Function ((.)) import Universum.Functor.Reexport (Functor (..)) --- | 'Prelude.map' generalized to 'Functor'.+-- $setup+-- >>> import Universum.Base (negate)+-- >>> import Universum.Bool (Bool (..), not)+-- >>> import Universum.Lifted (getLine)+-- >>> import Universum.Monad (Maybe (..))+-- >>> import Universum.String (toString)++{- | 'Prelude.map' generalized to 'Functor'.++>>> map not (Just True)+Just False+>>> map not [True,False,True,True]+[False,True,False,False]++-} map :: Functor f => (a -> b) -> f a -> f b map = fmap
src/Universum/Functor/Reexport.hs view
@@ -1,5 +1,7 @@ {-# LANGUAGE Safe #-} +-- | This module reexports functionality regarding 'Functor' type class.+ module Universum.Functor.Reexport ( module Control.Arrow , module Data.Bifunctor
src/Universum/Lifted/ST.hs view
@@ -1,3 +1,5 @@+-- | This module contains lifted version of 'XIO.stToIO' function.+ module Universum.Lifted.ST ( stToIO ) where
src/Universum/List/Reexport.hs view
@@ -1,6 +1,8 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE Trustworthy #-} +-- | This module reexports functinons to work with list, 'NonEmpty' and String types.+ module Universum.List.Reexport ( module Data.List @@ -18,7 +20,7 @@ transpose, unfoldr, unzip, unzip3, zip, zip3, zipWith, (++)) #if ( __GLASGOW_HASKELL__ >= 800 )-import Data.List.NonEmpty (head, init, last, tail)+import Data.List.NonEmpty (NonEmpty (..), head, init, last, nonEmpty, tail) #endif import GHC.Exts (sortWith)
src/Universum/List/Safe.hs view
@@ -1,6 +1,8 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE Trustworthy #-} +-- | This module contains safe functions to work with list type (mostly with 'NonEmpty').+ module Universum.List.Safe ( list , uncons@@ -12,8 +14,8 @@ #if ( __GLASGOW_HASKELL__ >= 800 ) import Universum.Applicative (Applicative, pass)+import Universum.List.Reexport (NonEmpty (..)) import Universum.Monad (Monad (..))-import Universum.Monoid (NonEmpty (..)) #endif import Universum.Functor (fmap)@@ -22,9 +24,10 @@ -- $setup -- >>> import Universum.Applicative (pure) -- >>> import Universum.Base ((==), even)--- >>> import Universum.Bool (Bool (..))+-- >>> import Universum.Bool (Bool (..), not) -- >>> import Universum.Container (length) -- >>> import Universum.Function (($))+-- >>> import Universum.Print (print) -- | Returns default list if given list is empty. -- Otherwise applies given function to every element.@@ -51,7 +54,13 @@ uncons (x:xs) = Just (x, xs) #if ( __GLASGOW_HASKELL__ >= 800 )--- | Performs given action over 'NonEmpty' list if given list is non empty.+{- | Performs given action over 'NonEmpty' list if given list is non empty.++>>> whenNotNull [] $ \(b :| _) -> print (not b)+>>> whenNotNull [False,True] $ \(b :| _) -> print (not b)+True++-} whenNotNull :: Applicative f => [a] -> (NonEmpty a -> f ()) -> f () whenNotNull [] _ = pass whenNotNull (x:xs) f = f (x :| xs)
src/Universum/Monad/Container.hs view
@@ -1,5 +1,8 @@ {-# LANGUAGE TypeFamilies #-} +-- | This module exports functions which allow to process instances of+-- 'Container' type class in monadic way.+ module Universum.Monad.Container ( concatMapM , concatForM
src/Universum/Monad/Maybe.hs view
@@ -17,9 +17,9 @@ import Universum.Monad.Reexport (Maybe (..), Monad (..)) -- $setup--- >>> import Universum.Bool (Bool (..))+-- >>> import Universum.Bool (Bool (..), not) -- >>> import Universum.Function (($))--- >>> import Universum.Print (putTextLn)+-- >>> import Universum.Print (putTextLn, print) -- >>> import Universum.String (readMaybe) {- | Similar to 'fromMaybe' but with flipped arguments.@@ -36,9 +36,15 @@ mA ?: b = fromMaybe b mA {-# INLINE (?:) #-} --- | Specialized version of 'for_' for 'Maybe'. It's used for code readability.--- Also helps to avoid space leaks:--- <http://www.snoyman.com/blog/2017/01/foldable-mapm-maybe-and-recursive-functions Foldable.mapM_ space leak>.+{- | Specialized version of 'for_' for 'Maybe'. It's used for code readability.+Also helps to avoid space leaks:+<http://www.snoyman.com/blog/2017/01/foldable-mapm-maybe-and-recursive-functions Foldable.mapM_ space leak>.++>>> whenJust Nothing $ \b -> print (not b)+>>> whenJust (Just True) $ \b -> print (not b)+False++-} whenJust :: Applicative f => Maybe a -> (a -> f ()) -> f () whenJust (Just x) f = f x whenJust Nothing _ = pass
src/Universum/Monad/Reexport.hs view
@@ -1,6 +1,8 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE Trustworthy #-} +-- | This module reexports functions to work with monads.+ module Universum.Monad.Reexport ( -- * Reexport transformers module Control.Monad.Except
src/Universum/Monoid.hs view
@@ -1,13 +1,11 @@ {-# LANGUAGE CPP #-} +-- | This module reexports functions to work with monoids plus adds extra useful functions.+ module Universum.Monoid- (+ ( module Data.Monoid #if ( __GLASGOW_HASKELL__ >= 800 )- module Data.List.NonEmpty- , module Data.Monoid , module Data.Semigroup-#else- module Data.Monoid #endif , maybeToMonoid ) where@@ -16,9 +14,8 @@ Monoid (..), Product (..), Sum (..)) #if ( __GLASGOW_HASKELL__ >= 800 )-import Data.List.NonEmpty (NonEmpty (..), nonEmpty) import Data.Semigroup (Option (..), Semigroup (sconcat, stimes, (<>)), WrappedMonoid, cycle1,- mtimesDefault, stimesIdempotent, stimesIdempotentMonoid, stimesMonoid)+ mtimesDefault, stimesIdempotent, stimesIdempotentMonoid, stimesMonoid) #endif import Universum.Monad.Reexport (Maybe, fromMaybe)
src/Universum/Nub.hs view
@@ -32,10 +32,26 @@ import Data.Hashable (Hashable) import Data.HashSet as HashSet import Data.Ord (Ord)-import Prelude ((.))+import Data.Set (Set)+import Prelude (Bool, Char, (.)) import qualified Data.Set as Set +-- Liquid Haskell check for duplicates.+{-@ type ListUnique a = {v : [a] | NoDups v} @-}++{-@ predicate NoDups L = Set_emp (dups L) @-}++{-@ measure dups :: [a] -> (Set a)+ dups ([]) = {v | Set_emp v}+ dups (x:xs) = {v | v =+ if (Set_mem x (listElts xs))+ then (Set_cup (Set_sng x) (dups xs))+ else (dups xs)}+@-}++{-@ Set.toList :: Set a -> ListUnique a @-}+ -- | Like 'Prelude.nub' but runs in @O(n * log n)@ time and requires 'Ord'. -- -- >>> ordNub [3, 3, 3, 2, 2, -1, 1]@@ -66,6 +82,7 @@ -- -- >>> sortNub [3, 3, 3, 2, 2, -1, 1] -- [-1,1,2,3]+{-@ sortNub :: [a] -> ListUnique a @-} sortNub :: (Ord a) => [a] -> [a] sortNub = Set.toList . Set.fromList
src/Universum/String/Conversion.hs view
@@ -4,6 +4,12 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TypeSynonymInstances #-} +-- | This module implements type class which allow to have conversion to and+-- from 'Text', 'String' and 'ByteString' types (including both strict and lazy+-- versions). Usually you need to export 'Text' modules qualified and use+-- 'T.pack' \/ 'T.unpack' functions to convert to\/from 'Text'. Now you can+-- just use 'toText' \/ 'toString' functions.+ module Universum.String.Conversion ( -- * Convenient type aliases LText
src/Universum/String/Reexport.hs view
@@ -1,3 +1,5 @@+-- | This module reexports functions to work with 'Text' and 'ByteString' types.+ module Universum.String.Reexport ( -- * String module Data.String
src/Universum/Unsafe.hs view
@@ -28,8 +28,11 @@ import Data.Maybe (fromJust) import Universum.Base (Int)-import Universum.Function (flip) +-- Non empty list definition for @liquidhaskell@.+{-@ type NonEmptyList a = {xs : [a] | len xs > 0} @-}+ -- | Similar to '!!' but with flipped arguments.+{-@ at :: n : Nat -> {xs : NonEmptyList a | len xs > n} -> a @-} at :: Int -> [a] -> a-at = flip (!!)+at n xs = xs !! n
src/Universum/VarArg.hs view
@@ -17,6 +17,7 @@ -- >>> import Prelude (show) -- >>> import Data.List (zip5) +-- | This type class allows to implement variadic composition operator. class SuperComposition a b c | a b -> c where -- | Allows to apply function to result of another function with multiple -- arguments.
universum.cabal view
@@ -1,5 +1,5 @@ name: universum-version: 1.1.0+version: 1.1.1 cabal-version: >=1.18 build-type: Simple license: MIT@@ -16,6 +16,7 @@ author: Stephen Diehl, @serokell tested-with: GHC ==7.10.3 GHC ==8.0.2 GHC ==8.2.2 extra-doc-files: CHANGES.md+ CONTRIBUTING.md README.md source-repository head@@ -117,19 +118,19 @@ ghc-options: -threaded benchmark universum-benchmark+ + if impl(ghc ==7.10.3)+ build-depends:+ semigroups >=0.18 type: exitcode-stdio-1.0 main-is: Main.hs build-depends: base >=4.9.1.0 && <5, universum -any, containers >=0.5.7.1,- criterion >=1.1.4.0,- deepseq >=1.4.2.0,- hashable >=1.2.6.1,- mtl >=2.2.1,- semigroups >=0.18.3,- text >=1.2.2.2,+ gauge >=0.1.3, unordered-containers >=0.2.8.0 default-language: Haskell2010+ default-extensions: NoImplicitPrelude ScopedTypeVariables hs-source-dirs: benchmark- ghc-options: -Wall -O2 -threaded -rtsopts -with-rtsopts=-N+ ghc-options: -Wall -threaded -rtsopts -with-rtsopts=-N