diff --git a/CHANGES.md b/CHANGES.md
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,3 +1,23 @@
+1.1.0
+=====
+
+* [#144](https://github.com/serokell/universum/issues/144):
+  Add `Exc` pattern synonym.
+* [#60](https://github.com/serokell/universum/issues/60):
+  Reexport `Natural` type from `Numeric.Natura` module.
+* [#118](https://github.com/serokell/universum/issues/118):
+  Reexport `Type` from `Data.Kind` module.
+* [#130](https://github.com/serokell/universum/issues/130):
+  Merge `ToList` and `Container` type classes into single type class `Container`.
+* [#15](https://github.com/serokell/universum/issues/15):
+  Add `?:` function to `Universum.Monad.Maybe`.
+* [#128](https://github.com/serokell/universum/issues/128):
+  Add `Unsafe` module with unsafe functions to works with lists and `Maybe`.
+* [#129](https://github.com/serokell/universum/issues/129):
+  Reexport `id`.
+* [#136](https://github.com/serokell/universum/issues/136):
+  Change `foldl'` type back, add `flipfoldl'` instead.
+
 1.0.4.1
 =====
 
@@ -63,6 +83,8 @@
   Remove `NontrivialContainer` constraint alias.
 * [#56](https://github.com/serokell/universum/issues/56):
   Make `elem` and `notElem` faster for `Set` and `HashSet` by introducing `ElementConstraint` associated type family.
+* Remove `Unsafe` module. Though, see issue [#128](https://github.com/serokell/universum/issues/128)
+  for disuccion regarding possible return of this module.
 
 0.9.1
 =====
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -59,6 +59,8 @@
 
 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
+   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)
@@ -116,17 +118,18 @@
 Gotchas
 -------
 
-* `id` is renamed to `identity` (because it's nice to be able to use `id` as a variable name).
 * `head`, `tail`, `last`, `init` work with `NonEmpty a` instead of `[a]`.
 * Safe analogue for `head` function: `safeHead :: [a] -> Maybe a`.
-* `undefined` triggers a compiler warning, which is probably not what you want. Either use `throwIO`, `Except`, or `error`.
+* `undefined` triggers a compiler warning, which is probably not what you want. Either use `throwIO`, `Except`, `error` or `bug`.
 * `map` is `fmap` now.
-* `sortOn` is available without import. This function efficiently sorts a list based on some
-  property of its elements (e.g. `sortOn length` would sort elements by length).
+* Multiple sorting functions are available without imports:
+  + `sortBy :: (a -> a -> Ordering) -> [a] -> [a]`: sorts list using given custom comparator.
+  + `sortWith :: Ord b => (a -> b) -> [a] -> [a]`: sorts a list based on some property of its elements.
+  + `sortOn :: Ord b => (a -> b) -> [a] -> [a]`: just like `sortWith`, but more time-efficient if function is calculated slowly (though less space-efficient). So you should write `sortOn length` (would sort elements by length) but `sortWith fst` (would sort list of pairs by first element).
 * Functions `sum` and `product` are strict now, which makes them more efficient.
 * If you try to do something like `putStrLn "hi"`, you'll get an error message if
   `OverloadedStrings` is enabled – it happens because the compiler doesn't know what
-  type to infer for the string. Use `putText` in this case.
+  type to infer for the string. Use `putTextLn` in this case.
 * Since `show` doesn't come from `Show` anymore, you can't write `Show` instances easily.
   Either use autoderived instances or
   [`Buildable`](https://github.com/serokell/universum/blob/f2ccf8afd862e37ccd204c0ef9efde48a05c2d29/src/Universum.hs#L144).
@@ -143,7 +146,6 @@
 * As a consequence of previous point, some functions like `traverse_`, `forM_`, `sequenceA_`, etc.
   are generalized over `Container` type classes.
 * `error` takes `Text`.
-* `foldl'` takes a function with its arguments flipped compared with the `base` version.
 
 
 Things that you were already using, but now you don't have to import them explicitly
@@ -158,7 +160,7 @@
 Then, some commonly used types: `Map/HashMap/IntMap`, `Set/HashSet/IntSet`, `Seq`, `Text` and `ByteString`
 (as well as synonyms `LText` and `LByteString` for lazy versions).
 
-`liftIO` and `MonadIO` are exported by default. A lot of functions are generalized to `MonadIO`.
+`liftIO` and `MonadIO` are exported by default. A lot of `IO` functions are generalized to `MonadIO`.
 
 `deepseq` is exported. For instance, if you want to force deep evaluation of some value (in IO),
 you can write `evaluateNF a`. WHNF evaluation is possible with `evaluateWHNF a`.
@@ -176,7 +178,7 @@
 We export `Text` and `LText`, and some functions work with `Text` instead of `String` –
 specifically, IO functions (`readFile`, `putStrLn`, etc) and `show`. In fact, `show`
 is polymorphic and can produce strict or lazy `Text`, `String`, or `ByteString`.
-Also, `toS` can convert any string type to any string type, but you can use `toText`, `toByteString`, `toString` functions to convert to any specific type.
+Also, `toText/toLText/toString` can convert `Text|LText|String` types to `Text/LText/String`. If you want to convert to and from `ByteString` use `encodeUtf8/decodeUtf8` functions.
 
 ### Debugging and `undefined`s
 
@@ -201,7 +203,7 @@
 * `ordNub` and `sortNub` are _O(n log n)_ versions of `nub` (which is quadratic)
   and `hashNub` and `unstableNub` are almost _O(n)_ versions of `nub`.
 * `(&)` – reverse application. `x & f & g` instead of `g $ f $ x` is useful sometimes.
-* `pretty` and `prettyL` for converting `Buildable` into `Text` (can be used instead of `show`).
+* `pretty` and `prettyL` for converting `Buildable` into `Text` (suggested be used instead of `show`).
 * `whenM`, `unlessM`, `ifM`, `guardM` are available and do what you expect
   them to do (e.g. `whenM (doesFileExist "foo")`).
 * Very generalized version of `concatMapM`, too, is available and does what expected.
@@ -277,7 +279,16 @@
   for creating singleton containers. Even monomorhpic ones like `Text`.
 * `evaluateWHNF` and `evaluateNF` functions as clearer and lifted aliases for
   `evaluate` and `evaluate . force`.
-* `ToPairs` type class for data types that can be converted to list of pairs.
+* `ToPairs` type class for data types that can be converted to list of pairs (like `Map` or `HashMap` or `IntMap`).
+
+Projects that use Universum
+---------------------------
+
+- [cardano-report-server](https://github.com/input-output-hk/cardano-report-server)
+- [cardano-sl](https://github.com/input-output-hk/cardano-sl)
+- [importify](https://github.com/serokell/importify)
+- [log-warper](https://github.com/serokell/log-warper)
+- [orgstat](https://github.com/volhovm/orgstat)
 
 License
 -------
diff --git a/benchmark/Main.hs b/benchmark/Main.hs
--- a/benchmark/Main.hs
+++ b/benchmark/Main.hs
@@ -10,17 +10,17 @@
 import Data.List (group, head, nub, sort, zip5)
 import Data.Text (Text)
 
+import Universum.Container (flipfoldl', foldl')
 import Universum.Monad (concatMapM)
 import Universum.Nub (hashNub, ordNub, sortNub, unstableNub)
 import Universum.VarArg ((...))
 
 import qualified Data.Foldable as Foldable (elem)
 import qualified Data.HashSet as HashSet (fromList, insert)
-import qualified Data.List as List (foldl')
 import qualified Data.List.NonEmpty as NonEmpty
 import qualified Data.Set as Set (fromList)
 import qualified Data.Text as T
-import qualified Universum.Container as Container (elem, foldl')
+import qualified Universum.Container as Container (elem)
 
 main :: IO ()
 main = defaultMain
@@ -173,10 +173,9 @@
 -- | Checks that 'foldl'' is implemented efficiently for 'Universum.List'
 bgroupFold :: Benchmark
 bgroupFold = do
-    let testList        = [1..100000] :: [Int]
-    let universumFoldl' = Container.foldl' HashSet.insert mempty
-    let ghcFoldl'       = List.foldl' (\hashSet element -> 
-                          HashSet.insert element hashSet) mempty
-    bgroup "foldl'" [ bench "universum" $ nf universumFoldl' testList
-                    , bench "base"      $ nf ghcFoldl' testList
+    let testList   = [1..100000] :: [Int]
+    let flipFoldl' = flipfoldl' HashSet.insert mempty
+    let ghcFoldl'  = foldl' (\hashSet element -> HashSet.insert element hashSet) mempty
+    bgroup "foldl'" [ bench "flipped" $ nf flipFoldl' testList
+                    , bench "base"    $ nf ghcFoldl'  testList
                     ]
diff --git a/src/Universum/Base.hs b/src/Universum/Base.hs
--- a/src/Universum/Base.hs
+++ b/src/Universum/Base.hs
@@ -11,6 +11,7 @@
        , module Data.Char
        , module Data.Int
        , module Data.Word
+       , Natural
 
          -- * Base type classes
        , module Data.Eq
@@ -22,11 +23,10 @@
        , module System.IO
 
          -- * Base GHC types
-#if ( __GLASGOW_HASKELL__ >= 710 )
        , module Data.Proxy
        , module Data.Typeable
        , module Data.Void
-#endif
+
        , module GHC.Base
        , module GHC.Enum
        , module GHC.Exts
@@ -47,6 +47,9 @@
        , module GHC.OverloadedLabels
        , module GHC.ExecutionStack
        , module GHC.Stack
+
+         -- * Data.Kind
+       , Type
 #endif
 
        , ($!)
@@ -57,6 +60,7 @@
 import Data.Char (chr)
 import Data.Int (Int, Int16, Int32, Int64, Int8)
 import Data.Word (Word, Word16, Word32, Word64, Word8, byteSwap16, byteSwap32, byteSwap64)
+import Numeric.Natural (Natural)
 
 -- IO
 import System.IO (FilePath, Handle, IOMode (..), stderr, stdin, stdout, withFile)
@@ -98,24 +102,13 @@
                   prettyCallStack, prettySrcLoc, withFrozenCallStack)
 #endif
 
+#if ( __GLASGOW_HASKELL__ >= 800 )
+-- TODO: move Constraint here later
+import Data.Kind (Type)
+#endif
+
 -- $setup
 -- >>> import Universum.Function (const, ($))
-
--- Pending GHC 8.2 we'll expose these.
-
-{-
-import GHC.Records as X (
-    HasField(..)
-  )
-
-<<<<<<< HEAD
-=======
-import Data.Kind as X (
-    type (*)
-  , type Type
-  )
--}
-
 
 -- | Stricter version of 'Data.Function.$' operator.
 -- Default Prelude defines this at the toplevel module, so we do as well.
diff --git a/src/Universum/Container/Class.hs b/src/Universum/Container/Class.hs
--- a/src/Universum/Container/Class.hs
+++ b/src/Universum/Container/Class.hs
@@ -21,10 +21,11 @@
 
 module Universum.Container.Class
        ( -- * Foldable-like classes and methods
-         ToList    (..)
-       , ToPairs   (..)
+         ToPairs   (..)
        , Container (..)
 
+       , flipfoldl'
+
        , sum
        , product
 
@@ -64,8 +65,6 @@
 
 import qualified Data.Foldable as Foldable
 
-import qualified Data.List as List (null)
-
 import qualified Data.Sequence as SEQ
 
 import qualified Data.ByteString as BS
@@ -91,124 +90,6 @@
 -- >>> import qualified Data.HashMap.Strict as HashMap
 
 ----------------------------------------------------------------------------
--- Containers (e.g. tuples aren't containers)
-----------------------------------------------------------------------------
-
--- | Default implementation of 'Element' associated type family.
-type family ElementDefault (t :: *) :: * where
-    ElementDefault (f a) = a
-
--- | Type class for data types that can be converted to List.
--- Contains very small and safe subset of 'Foldable' functions.
---
--- You can define 'Tolist' by just defining 'toList' function.
--- But the following law should be met:
---
--- @'null' ≡ 'List.null' . 'toList'@
---
-class ToList t where
-    -- | Type of element for some container. Implemented as an asscociated type family because
-    -- some containers are monomorphic over element type (like 'T.Text', 'IntSet', etc.)
-    -- so we can't implement nice interface using old higher-kinded types
-    -- approach. Implementing this as an associated type family instead of
-    -- top-level family gives you more control over element types.
-    type Element t :: *
-    type Element t = ElementDefault t
-
-    -- | Convert container to list of elements.
-    --
-    -- >>> toList (Just True)
-    -- [True]
-    -- >>> toList @Text "aba"
-    -- "aba"
-    -- >>> :t toList @Text "aba"
-    -- toList @Text "aba" :: [Char]
-    toList :: t -> [Element t]
-    default toList :: (Foldable f, t ~ f a, Element t ~ a) => t -> [Element t]
-    toList = Foldable.toList
-    {-# INLINE toList #-}
-
-    -- | Checks whether container is empty.
-    --
-    -- >>> null @Text ""
-    -- True
-    -- >>> null @Text "aba"
-    -- False
-    null :: t -> Bool
-    null = List.null . toList
-    {-# INLINE null #-}
-
-----------------------------------------------------------------------------
--- Instances for monomorphic containers
-----------------------------------------------------------------------------
-
-instance ToList T.Text where
-    type Element T.Text = Char
-    toList = T.unpack
-    {-# INLINE toList #-}
-    null = T.null
-    {-# INLINE null #-}
-
-instance ToList TL.Text where
-    type Element TL.Text = Char
-    toList = TL.unpack
-    {-# INLINE toList #-}
-    null = TL.null
-    {-# INLINE null #-}
-
-instance ToList BS.ByteString where
-    type Element BS.ByteString = Word8
-    toList = BS.unpack
-    {-# INLINE toList #-}
-    null = BS.null
-    {-# INLINE null #-}
-
-instance ToList BSL.ByteString where
-    type Element BSL.ByteString = Word8
-    toList = BSL.unpack
-    {-# INLINE toList #-}
-    null = BSL.null
-    {-# INLINE null #-}
-
-instance ToList IntSet where
-    type Element IntSet = Int
-    toList = IS.toList
-    {-# INLINE toList #-}
-    null = IS.null
-    {-# INLINE null #-}
-
-----------------------------------------------------------------------------
--- Boilerplate instances (duplicate Foldable)
-----------------------------------------------------------------------------
-
--- Basic types
-instance ToList [a]
-instance ToList (Maybe a)
-instance ToList (Either a b)
-instance ToList (Identity a)
-instance ToList (Const a b)
-
-#if __GLASGOW_HASKELL__ >= 800
--- Algebraic types
-instance ToList (Dual a)
-instance ToList (First a)
-instance ToList (Last a)
-instance ToList (Product a)
-instance ToList (Sum a)
-instance ToList (NonEmpty a)
-instance ToList (ZipList a)
-#endif
-
--- Containers
-instance ToList (HashMap k v)
-instance ToList (HashSet v)
-instance ToList (IntMap v)
-instance ToList (Map k v)
-instance ToList (Set v)
-instance ToList (Seq a)
-instance ToList (Vector a)
-
-----------------------------------------------------------------------------
 -- ToPairs
 ----------------------------------------------------------------------------
 
@@ -284,19 +165,63 @@
     elems   = M.elems
     {-# INLINE elems #-}
 
-
 ----------------------------------------------------------------------------
--- Additional operations that don't make much sense for e.g. Maybe
+-- Containers (e.g. tuples and Maybe aren't containers)
 ----------------------------------------------------------------------------
 
--- | A class for 'ToList's that aren't trivial like 'Maybe' (e.g. can hold
--- more than one value)
-class ToList t => Container t where
+-- | Default implementation of 'Element' associated type family.
+type family ElementDefault (t :: *) :: * where
+    ElementDefault (f a) = a
+
+-- | Very similar to 'Foldable' but also allows instances for monomorphic types
+-- like 'Text' but forbids instances for 'Maybe' and similar. This class is used as
+-- a replacement for 'Foldable' type class. It solves the following problems:
+--
+-- 1. 'length', 'foldr' and other functions work on more types for which it makes sense.
+-- 2. You can't accidentally use 'length' on polymorphic 'Foldable' (like list),
+--    replace list with 'Maybe' and then debug error for two days.
+-- 3. More efficient implementaions of functions for polymorphic types (like 'elem' for 'Set').
+--
+-- The drawbacks:
+--
+-- 1. Type signatures of polymorphic functions look more scary.
+-- 2. Orphan instances are involved if you want to use 'foldr' (and similar) on types from libraries.
+class Container t where
+    -- | Type of element for some container. Implemented as an asscociated type family because
+    -- some containers are monomorphic over element type (like 'T.Text', 'IntSet', etc.)
+    -- so we can't implement nice interface using old higher-kinded types
+    -- approach. Implementing this as an associated type family instead of
+    -- top-level family gives you more control over element types.
+    type Element t :: *
+    type Element t = ElementDefault t
+
     -- | Constraint for elements. This can be used to implement more efficient
-    -- implementation of some methods.
+    -- implementation of some methods. For example 'elem' for 'Set' and 'HashSet'.
     type ElementConstraint t :: * -> Constraint
     type ElementConstraint t = Eq
 
+    -- | Convert container to list of elements.
+    --
+    -- >>> toList @Text "aba"
+    -- "aba"
+    -- >>> :t toList @Text "aba"
+    -- toList @Text "aba" :: [Char]
+    toList :: t -> [Element t]
+    default toList :: (Foldable f, t ~ f a, Element t ~ a) => t -> [Element t]
+    toList = Foldable.toList
+    {-# INLINE toList #-}
+
+    -- | Checks whether container is empty.
+    --
+    -- >>> null @Text ""
+    -- True
+    -- >>> null @Text "aba"
+    -- False
+    null :: t -> Bool
+    default null :: (Foldable f, t ~ f a, Element t ~ a) => t -> Bool
+    null = Foldable.null
+    {-# INLINE null #-}
+
     foldr :: (Element t -> b -> b) -> b -> t -> b
     default foldr :: (Foldable f, t ~ f a, Element t ~ a) => (Element t -> b -> b) -> b -> t -> b
     foldr = Foldable.foldr
@@ -307,9 +232,9 @@
     foldl = Foldable.foldl
     {-# INLINE foldl #-}
 
-    foldl' :: (Element t -> b -> b) -> b -> t -> b
-    default foldl' :: (Foldable f, t ~ f a, Element t ~ a) => (Element t -> b -> b) -> b -> t -> b
-    foldl' f = Foldable.foldl' (flip f)
+    foldl' :: (b -> Element t -> b) -> b -> t -> b
+    default foldl' :: (Foldable f, t ~ f a, Element t ~ a) => (b -> Element t -> b) -> b -> t -> b
+    foldl' = Foldable.foldl'
     {-# INLINE foldl' #-}
 
     length :: t -> Int
@@ -411,11 +336,16 @@
 ----------------------------------------------------------------------------
 
 instance Container T.Text where
+    type Element T.Text = Char
+    toList = T.unpack
+    {-# INLINE toList #-}
+    null = T.null
+    {-# INLINE null #-}
     foldr = T.foldr
     {-# INLINE foldr #-}
     foldl = T.foldl
     {-# INLINE foldl #-}
-    foldl' f = T.foldl' (flip f)
+    foldl' = T.foldl'
     {-# INLINE foldl' #-}
     foldr1 = T.foldr1
     {-# INLINE foldr1 #-}
@@ -439,11 +369,16 @@
     {-# INLINE safeHead #-}
 
 instance Container TL.Text where
+    type Element TL.Text = Char
+    toList = TL.unpack
+    {-# INLINE toList #-}
+    null = TL.null
+    {-# INLINE null #-}
     foldr = TL.foldr
     {-# INLINE foldr #-}
     foldl = TL.foldl
     {-# INLINE foldl #-}
-    foldl' f = TL.foldl' (flip f)
+    foldl' = TL.foldl'
     {-# INLINE foldl' #-}
     foldr1 = TL.foldr1
     {-# INLINE foldr1 #-}
@@ -468,11 +403,16 @@
     {-# INLINE safeHead #-}
 
 instance Container BS.ByteString where
+    type Element BS.ByteString = Word8
+    toList = BS.unpack
+    {-# INLINE toList #-}
+    null = BS.null
+    {-# INLINE null #-}
     foldr = BS.foldr
     {-# INLINE foldr #-}
     foldl = BS.foldl
     {-# INLINE foldl #-}
-    foldl' f = BS.foldl' (flip f)
+    foldl' = BS.foldl'
     {-# INLINE foldl' #-}
     foldr1 = BS.foldr1
     {-# INLINE foldr1 #-}
@@ -498,11 +438,16 @@
     {-# INLINE safeHead #-}
 
 instance Container BSL.ByteString where
+    type Element BSL.ByteString = Word8
+    toList = BSL.unpack
+    {-# INLINE toList #-}
+    null = BSL.null
+    {-# INLINE null #-}
     foldr = BSL.foldr
     {-# INLINE foldr #-}
     foldl = BSL.foldl
     {-# INLINE foldl #-}
-    foldl' f = BSL.foldl' (flip f)
+    foldl' = BSL.foldl'
     {-# INLINE foldl' #-}
     foldr1 = BSL.foldr1
     {-# INLINE foldr1 #-}
@@ -528,11 +473,16 @@
     {-# INLINE safeHead #-}
 
 instance Container IntSet where
+    type Element IntSet = Int
+    toList = IS.toList
+    {-# INLINE toList #-}
+    null = IS.null
+    {-# INLINE null #-}
     foldr = IS.foldr
     {-# INLINE foldr #-}
     foldl = IS.foldl
     {-# INLINE foldl #-}
-    foldl' f = IS.foldl' (flip f)
+    foldl' = IS.foldl'
     {-# INLINE foldl' #-}
     length = IS.size
     {-# INLINE length #-}
@@ -596,6 +546,16 @@
 
 -- TODO: I should put different strings for different versions but I'm too lazy to do it...
 
+{- | Similar to 'foldl'' but takes a function with its arguments flipped.
+
+>>> flipfoldl' (/) 5 [2,3] :: Rational
+15 % 2
+
+-}
+flipfoldl' :: (Container t, Element t ~ a) => (a -> b -> b) -> b -> t -> b
+flipfoldl' f = foldl' (flip f)
+{-# INLINE flipfoldl' #-}
+
 #if MIN_VERSION_base(4,10,1)
 -- | Stricter version of 'Prelude.sum'.
 --
@@ -710,51 +670,17 @@
         :$$: Text ""
 #endif
 
-#define DISALLOW_TO_LIST_8(t, z) \
-    instance TypeError (DisallowInstance z) => \
-      ToList (t) where { \
-        toList = undefined; \
-        null = undefined; } \
-
-#define DISALLOW_CONTAINER_8(t, z) \
-    instance TypeError (DisallowInstance z) => \
-      Container (t) where { \
-        foldr = undefined; \
-        foldl = undefined; \
-        foldl' = undefined; \
-        length = undefined; \
-        elem = undefined; \
-        maximum = undefined; \
-        minimum = undefined; } \
-
-#define DISALLOW_TO_LIST_7(t) \
-    instance ForbiddenFoldable (t) => ToList (t) where { \
-        toList = undefined; \
-        null = undefined; } \
-
-#define DISALLOW_CONTAINER_7(t) \
-    instance ForbiddenFoldable (t) => Container (t) where { \
-        foldr = undefined; \
-        foldl = undefined; \
-        foldl' = undefined; \
-        length = undefined; \
-        elem = undefined; \
-        maximum = undefined; \
-        minimum = undefined; } \
-
 #if __GLASGOW_HASKELL__ >= 800
-DISALLOW_TO_LIST_8((a, b),"tuples")
-DISALLOW_CONTAINER_8((a, b),"tuples")
-DISALLOW_CONTAINER_8(Maybe a,"Maybe")
-DISALLOW_CONTAINER_8(Identity a,"Identity")
-DISALLOW_CONTAINER_8(Either a b,"Either")
+instance TypeError (DisallowInstance "tuple")    => Container (a, b)
+instance TypeError (DisallowInstance "Maybe")    => Container (Maybe a)
+instance TypeError (DisallowInstance "Either")   => Container (Either a b)
+instance TypeError (DisallowInstance "Identity") => Container (Identity a)
 #else
 class ForbiddenFoldable a
-DISALLOW_TO_LIST_7((a, b))
-DISALLOW_CONTAINER_7((a, b))
-DISALLOW_CONTAINER_7(Maybe a)
-DISALLOW_CONTAINER_7(Identity a)
-DISALLOW_CONTAINER_7(Either a b)
+instance ForbiddenFoldable (a, b)       => Container (a, b)
+instance ForbiddenFoldable (Maybe a)    => Container (Maybe a)
+instance ForbiddenFoldable (Either a b) => Container (Either a b)
+instance ForbiddenFoldable (Identity a) => Container (Identity a)
 #endif
 
 ----------------------------------------------------------------------------
diff --git a/src/Universum/Exception.hs b/src/Universum/Exception.hs
--- a/src/Universum/Exception.hs
+++ b/src/Universum/Exception.hs
@@ -1,6 +1,8 @@
 {-# LANGUAGE CPP                   #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE PatternSynonyms       #-}
 {-# LANGUAGE Safe                  #-}
+{-# LANGUAGE ViewPatterns          #-}
 
 -- | Re-exports most useful functionality from 'safe-exceptions'. Also
 -- provides some functions to work with exceptions over 'MonadError'.
@@ -10,6 +12,7 @@
 #if ( __GLASGOW_HASKELL__ >= 800 )
        , Bug (..)
        , bug
+       , pattern Exc
 #endif
        , note
        ) where
@@ -20,9 +23,9 @@
                                catchAny, displayException, finally, handleAny, mask_, onException,
                                throwM, try, tryAny)
 
-import Control.Applicative (Applicative (pure))
 import Control.Monad.Except (MonadError, throwError)
-import Data.Maybe (Maybe, maybe)
+import Universum.Applicative (Applicative (pure))
+import Universum.Monad (Maybe (..), maybe)
 
 #if ( __GLASGOW_HASKELL__ >= 800 )
 import Data.List ((++))
@@ -55,4 +58,33 @@
 #else
 note :: (MonadError e m, Applicative m) => e -> Maybe a -> m a
 note err = maybe (throwError err) pure
+#endif
+
+
+#if ( __GLASGOW_HASKELL__ >= 800 )
+{- | Pattern synonym to easy pattern matching on exceptions. So intead of
+writing something like this:
+
+@
+isNonCriticalExc e
+    | Just (_ :: NodeAttackedError) <- fromException e = True
+    | Just DialogUnexpected{} <- fromException e = True
+    | otherwise = False
+@
+
+you can use 'Exc' pattern synonym:
+
+@
+isNonCriticalExc = \case
+    Exc (_ :: NodeAttackedError) -> True  -- matching all exceptions of type 'NodeAttackedError'
+    Exc DialogUnexpected{} -> True
+    _ -> False
+@
+
+This pattern is bidirectional. You can use @Exc e@ instead of @toException e@.
+-}
+pattern Exc :: Exception e => e -> SomeException
+pattern Exc e <- (fromException -> Just e)
+  where
+    Exc e = toException e
 #endif
diff --git a/src/Universum/Function.hs b/src/Universum/Function.hs
--- a/src/Universum/Function.hs
+++ b/src/Universum/Function.hs
@@ -3,8 +3,9 @@
        , identity
        ) where
 
-import Data.Function (const, fix, flip, on, ($), (.))
+import Data.Function (const, fix, flip, id, on, ($), (.))
 
 -- | Renamed version of 'Prelude.id'.
 identity :: a -> a
-identity x = x
+identity = id
+{-# INLINE identity #-}
diff --git a/src/Universum/Monad/Maybe.hs b/src/Universum/Monad/Maybe.hs
--- a/src/Universum/Monad/Maybe.hs
+++ b/src/Universum/Monad/Maybe.hs
@@ -3,7 +3,8 @@
 -- | Utility functions to work with 'Data.Maybe' data type as monad.
 
 module Universum.Monad.Maybe
-       ( whenJust
+       ( (?:)
+       , whenJust
        , whenJustM
        , whenNothing
        , whenNothing_
@@ -12,12 +13,28 @@
        ) where
 
 import Universum.Applicative (Applicative, pass, pure)
+import Universum.Monad.Reexport (fromMaybe)
 import Universum.Monad.Reexport (Maybe (..), Monad (..))
 
 -- $setup
 -- >>> import Universum.Bool (Bool (..))
 -- >>> import Universum.Function (($))
 -- >>> import Universum.Print (putTextLn)
+-- >>> import Universum.String (readMaybe)
+
+{- | Similar to 'fromMaybe' but with flipped arguments.
+
+>>> readMaybe "True" ?: False
+True
+
+>>> readMaybe "Tru" ?: False
+False
+
+-}
+infixr 0 ?:
+(?:) :: Maybe a -> a -> a
+mA ?: b = fromMaybe b mA
+{-# INLINE (?:) #-}
 
 -- | Specialized version of 'for_' for 'Maybe'. It's used for code readability.
 -- Also helps to avoid space leaks:
diff --git a/src/Universum/Unsafe.hs b/src/Universum/Unsafe.hs
new file mode 100644
--- /dev/null
+++ b/src/Universum/Unsafe.hs
@@ -0,0 +1,35 @@
+{-# LANGUAGE Unsafe #-}
+
+{- | Unsafe functions to work with lists and 'Maybe'.
+Sometimes unavoidable but better don't use them. This module
+is intended to be imported qualified and it's not even included
+in default prelude exports.
+
+@
+import qualified Universum.Unsafe as Unsafe
+
+foo :: [a] -> a
+foo = Unsafe.head
+@
+
+-}
+
+module Universum.Unsafe
+       ( head
+       , tail
+       , init
+       , last
+       , at
+       , (!!)
+       , fromJust
+       ) where
+
+import Data.List (head, init, last, tail, (!!))
+import Data.Maybe (fromJust)
+
+import Universum.Base (Int)
+import Universum.Function (flip)
+
+-- | Similar to '!!' but with flipped arguments.
+at :: Int -> [a] -> a
+at = flip (!!)
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,9 @@
+module Main where
+
+import Test.Tasty (defaultMain)
+
+import Test.Universum.Property (hedgehogTestTree)
+
+main :: IO ()
+main = do
+    defaultMain hedgehogTestTree
diff --git a/test/Test/Universum/Property.hs b/test/Test/Universum/Property.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Universum/Property.hs
@@ -0,0 +1,129 @@
+module Test.Universum.Property
+        ( hedgehogTestTree
+        ) where
+
+import Universum 
+
+import Data.List (nub)
+import Hedgehog (Property, Gen, MonadGen, forAll, property, assert, (===))
+import Test.Tasty (testGroup, TestTree)
+import Test.Tasty.Hedgehog
+
+import qualified Universum as U
+import qualified Hedgehog.Gen              as Gen
+import qualified Hedgehog.Range            as Range
+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
+
+
+
+hedgehogTestTree :: TestTree
+hedgehogTestTree = testGroup "Tests" [utfProps, listProps, boolMProps]
+
+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
+    ]
+
+unicode' :: MonadGen m => m U.Char
+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'
+
+-- "\65534" fails, but this is from BU.toString
+-- > import qualified Data.ByteString.UTF8 as BU
+-- > BU.toString (BU.fromString "\65534") == "\65533"
+-- > True 
+
+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)
+
diff --git a/universum.cabal b/universum.cabal
--- a/universum.cabal
+++ b/universum.cabal
@@ -1,5 +1,5 @@
 name: universum
-version: 1.0.4.1
+version: 1.1.0
 cabal-version: >=1.18
 build-type: Simple
 license: MIT
@@ -62,16 +62,17 @@
         Universum.String.Conversion
         Universum.String.Reexport
         Universum.TypeOps
+        Universum.Unsafe
         Universum.VarArg
     build-depends:
         base >=4.8 && <5,
-        bytestring >=0.10.8.2,
-        containers >=0.5.10.2,
-        deepseq >=1.4.3.0,
+        bytestring >=0.10.8.1,
+        containers >=0.5.7.1,
+        deepseq >=1.4.2.0,
         ghc-prim >=0.4.0.0,
         hashable >=1.2.6.1,
-        microlens >=0.4.8.3,
-        microlens-mtl >=0.1.11.1,
+        microlens >=0.4.8.1,
+        microlens-mtl >=0.1.11.0,
         mtl >=2.2.1,
         safe-exceptions >=0.1.6.0,
         stm >=2.4.4.1,
@@ -87,13 +88,30 @@
     hs-source-dirs: src
     ghc-options: -Wall -fwarn-implicit-prelude
 
+test-suite  universum-test
+    type: exitcode-stdio-1.0
+    main-is: Spec.hs
+    build-depends:
+        base >=4.8 && <5,
+        universum -any,
+        bytestring >=0.10.8.1,
+        text >=1.2.2.2,
+        utf8-string >=1.0.1.1,
+        hedgehog >=0.5.1,
+        tasty >=0.11.3,
+        tasty-hedgehog >=0.1.0.2
+    default-language: Haskell2010
+    hs-source-dirs: test
+    other-modules:
+        Test.Universum.Property
+    ghc-options: -Wall -threaded
 test-suite  universum-doctest
     type: exitcode-stdio-1.0
     main-is: Doctest.hs
     build-depends:
         base >=4.8 && <5,
-        doctest >=0.13.0,
-        Glob >=0.9.1
+        doctest >=0.11.4,
+        Glob >=0.8.0
     default-language: Haskell2010
     hs-source-dirs: test
     ghc-options: -threaded
@@ -102,11 +120,11 @@
     type: exitcode-stdio-1.0
     main-is: Main.hs
     build-depends:
-        base >=4.10.1.0 && <5,
+        base >=4.9.1.0 && <5,
         universum -any,
-        containers >=0.5.10.2,
-        criterion >=1.2.6.0,
-        deepseq >=1.4.3.0,
+        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,
