packages feed

base-compat 0.8.2 → 0.9.0

raw patch · 38 files changed

+1126/−38 lines, 38 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Control.Monad.Compat: (<$!>) :: Monad m => (a -> b) -> m a -> m b
- Control.Monad.Compat: foldM :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b
- Control.Monad.Compat: foldM_ :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m ()
- Control.Monad.Compat: forM :: (Traversable t, Monad m) => t a -> (a -> m b) -> m (t b)
- Control.Monad.Compat: forM_ :: (Foldable t, Monad m) => t a -> (a -> m b) -> m ()
- Control.Monad.Compat: guard :: Alternative f => Bool -> f ()
- Control.Monad.Compat: mapM :: Traversable t => forall a (m :: * -> *) b. Monad m => (a -> m b) -> t a -> m (t b)
- Control.Monad.Compat: mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()
- Control.Monad.Compat: msum :: (Foldable t, MonadPlus m) => t (m a) -> m a
- Control.Monad.Compat: sequence :: Traversable t => forall (m :: * -> *) a. Monad m => t (m a) -> m (t a)
- Control.Monad.Compat: sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()
- Control.Monad.Compat: unless :: Applicative f => Bool -> f () -> f ()
- Control.Monad.Compat: when :: Applicative f => Bool -> f () -> f ()
- Data.Foldable.Compat: length :: Foldable t => t a -> Int
- Data.Foldable.Compat: null :: Foldable t => t a -> Bool
- Data.List.Compat: all :: Foldable t => (a -> Bool) -> t a -> Bool
- Data.List.Compat: and :: Foldable t => t Bool -> Bool
- Data.List.Compat: any :: Foldable t => (a -> Bool) -> t a -> Bool
- Data.List.Compat: concat :: Foldable t => t [a] -> [a]
- Data.List.Compat: concatMap :: Foldable t => (a -> [b]) -> t a -> [b]
- Data.List.Compat: elem :: (Foldable t, Eq a) => a -> t a -> Bool
- Data.List.Compat: find :: Foldable t => (a -> Bool) -> t a -> Maybe a
- Data.List.Compat: foldl :: Foldable t => forall b a. (b -> a -> b) -> b -> t a -> b
- Data.List.Compat: foldl' :: Foldable t => forall b a. (b -> a -> b) -> b -> t a -> b
- Data.List.Compat: foldl1 :: Foldable t => forall a. (a -> a -> a) -> t a -> a
- Data.List.Compat: foldr :: Foldable t => forall a b. (a -> b -> b) -> b -> t a -> b
- Data.List.Compat: foldr1 :: Foldable t => forall a. (a -> a -> a) -> t a -> a
- Data.List.Compat: isSubsequenceOf :: Eq a => [a] -> [a] -> Bool
- Data.List.Compat: length :: Foldable t => t a -> Int
- Data.List.Compat: mapAccumL :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)
- Data.List.Compat: mapAccumR :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)
- Data.List.Compat: maximum :: (Foldable t, Ord a) => t a -> a
- Data.List.Compat: maximumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a
- Data.List.Compat: minimum :: (Foldable t, Ord a) => t a -> a
- Data.List.Compat: minimumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a
- Data.List.Compat: notElem :: (Foldable t, Eq a) => a -> t a -> Bool
- Data.List.Compat: nub :: Eq a => [a] -> [a]
- Data.List.Compat: nubBy :: (a -> a -> Bool) -> [a] -> [a]
- Data.List.Compat: null :: Foldable t => t a -> Bool
- Data.List.Compat: or :: Foldable t => t Bool -> Bool
- Data.List.Compat: product :: (Foldable t, Num a) => t a -> a
- Data.List.Compat: scanl' :: (b -> a -> b) -> b -> [a] -> [b]
- Data.List.Compat: sortOn :: Ord b => (a -> b) -> [a] -> [a]
- Data.List.Compat: sum :: (Foldable t, Num a) => t a -> a
- Data.List.Compat: uncons :: [a] -> Maybe (a, [a])
- Data.List.Compat: union :: Eq a => [a] -> [a] -> [a]
- Data.List.Compat: unionBy :: (a -> a -> Bool) -> [a] -> [a] -> [a]
+ Control.Concurrent.Compat: forkFinally :: IO a -> (Either SomeException a -> IO ()) -> IO ThreadId
+ Control.Concurrent.Compat: forkOSWithUnmask :: ((forall a. IO a -> IO a) -> IO ()) -> IO ThreadId
+ Control.Monad.Compat: filterM :: (Applicative m) => (a -> m Bool) -> [a] -> m [a]
+ Control.Monad.Compat: forever :: (Applicative f) => f a -> f b
+ Control.Monad.Compat: mapAndUnzipM :: (Applicative m) => (a -> m (b, c)) -> [a] -> m ([b], [c])
+ Control.Monad.Compat: replicateM :: (Applicative m) => Int -> m a -> m [a]
+ Control.Monad.Compat: replicateM_ :: (Applicative m) => Int -> m a -> m ()
+ Control.Monad.Compat: zipWithM :: (Applicative m) => (a -> b -> m c) -> [a] -> [b] -> m [c]
+ Control.Monad.Compat: zipWithM_ :: (Applicative m) => (a -> b -> m c) -> [a] -> [b] -> m ()
+ Control.Monad.ST.Lazy.Unsafe.Compat: unsafeIOToST :: IO a -> ST s a
+ Control.Monad.ST.Lazy.Unsafe.Compat: unsafeInterleaveST :: ST s a -> ST s a
+ Control.Monad.ST.Unsafe.Compat: unsafeIOToST :: IO a -> ST s a
+ Control.Monad.ST.Unsafe.Compat: unsafeInterleaveST :: ST s a -> ST s a
+ Control.Monad.ST.Unsafe.Compat: unsafeSTToIO :: ST s a -> IO a
+ Data.Functor.Const.Compat: Const :: a -> Const a b
+ Data.Functor.Const.Compat: [getConst] :: Const a b -> a
+ Data.Functor.Const.Compat: newtype Const a b :: * -> * -> *
+ Data.IORef.Compat: atomicModifyIORef' :: IORef a -> (a -> (a, b)) -> IO b
+ Data.IORef.Compat: atomicWriteIORef :: IORef a -> a -> IO ()
+ Data.IORef.Compat: modifyIORef' :: IORef a -> (a -> a) -> IO ()
+ Data.Ratio.Compat: denominator :: Ratio a -> a
+ Data.Ratio.Compat: numerator :: Ratio a -> a
+ Data.STRef.Compat: modifySTRef' :: STRef s a -> (a -> a) -> ST s ()
+ Data.String.Compat: lines :: String -> [String]
+ Data.String.Compat: type String = [Char]
+ Data.String.Compat: unlines :: [String] -> String
+ Data.String.Compat: unwords :: [String] -> String
+ Data.String.Compat: words :: String -> [String]
+ Foreign.ForeignPtr.Safe.Compat: addForeignPtrFinalizer :: FinalizerPtr a -> ForeignPtr a -> IO ()
+ Foreign.ForeignPtr.Safe.Compat: addForeignPtrFinalizerEnv :: FinalizerEnvPtr env a -> Ptr env -> ForeignPtr a -> IO ()
+ Foreign.ForeignPtr.Safe.Compat: castForeignPtr :: ForeignPtr a -> ForeignPtr b
+ Foreign.ForeignPtr.Safe.Compat: data ForeignPtr a :: * -> *
+ Foreign.ForeignPtr.Safe.Compat: finalizeForeignPtr :: ForeignPtr a -> IO ()
+ Foreign.ForeignPtr.Safe.Compat: mallocForeignPtr :: Storable a => IO (ForeignPtr a)
+ Foreign.ForeignPtr.Safe.Compat: mallocForeignPtrArray :: Storable a => Int -> IO (ForeignPtr a)
+ Foreign.ForeignPtr.Safe.Compat: mallocForeignPtrArray0 :: Storable a => Int -> IO (ForeignPtr a)
+ Foreign.ForeignPtr.Safe.Compat: mallocForeignPtrBytes :: Int -> IO (ForeignPtr a)
+ Foreign.ForeignPtr.Safe.Compat: newForeignPtr :: FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)
+ Foreign.ForeignPtr.Safe.Compat: newForeignPtrEnv :: FinalizerEnvPtr env a -> Ptr env -> Ptr a -> IO (ForeignPtr a)
+ Foreign.ForeignPtr.Safe.Compat: newForeignPtr_ :: Ptr a -> IO (ForeignPtr a)
+ Foreign.ForeignPtr.Safe.Compat: touchForeignPtr :: ForeignPtr a -> IO ()
+ Foreign.ForeignPtr.Safe.Compat: type FinalizerEnvPtr env a = FunPtr (Ptr env -> Ptr a -> IO ())
+ Foreign.ForeignPtr.Safe.Compat: type FinalizerPtr a = FunPtr (Ptr a -> IO ())
+ Foreign.ForeignPtr.Safe.Compat: withForeignPtr :: ForeignPtr a -> (Ptr a -> IO b) -> IO b
+ Foreign.ForeignPtr.Unsafe.Compat: unsafeForeignPtrToPtr :: ForeignPtr a -> Ptr a
+ Foreign.Marshal.Unsafe.Compat: unsafeLocalState :: IO a -> a
+ Prelude.Compat: errorWithoutStackTrace :: [Char] -> a
+ System.IO.Unsafe.Compat: unsafeDupablePerformIO :: IO a -> a
+ System.IO.Unsafe.Compat: unsafeFixIO :: (a -> IO a) -> IO a
- Control.Monad.Compat: class Monad (m :: * -> *)
+ Control.Monad.Compat: class Applicative m => Monad (m :: * -> *)
- Control.Monad.Compat: class Monad m => MonadPlus (m :: * -> *)
+ Control.Monad.Compat: class (Alternative m, Monad m) => MonadPlus (m :: * -> *)
- Debug.Trace.Compat: traceM :: Monad m => String -> m ()
+ Debug.Trace.Compat: traceM :: (Applicative f) => String -> f ()
- Debug.Trace.Compat: traceShowM :: (Show a, Monad m) => a -> m ()
+ Debug.Trace.Compat: traceShowM :: (Show a, Applicative f) => a -> f ()
- Prelude.Compat: class Monad (m :: * -> *)
+ Prelude.Compat: class Applicative m => Monad (m :: * -> *)

Files

CHANGES.markdown view
@@ -1,3 +1,26 @@+## Changes in 0.9.0+ - Sync with `base-4.9`/GHC 8.0+ - Weakened `RealFloat` constraints on `realPart`, `imagPart`, `conjugate`,+   `mkPolar`, and `cis` in `Data.Complex.Compat`+ - Backport `Foreign.ForeignPtr.Safe` and `Foreign.Marshal.Safe`+ - Generalize `filterM`, `forever`, `mapAndUnzipM`, `zipWithM`, `zipWithM_`,+   `replicateM`, and `replicateM_` in `Control.Monad` from `Monad` to+   `Applicative`+ - Backport `.Unsafe.Compat` modules (for `Control.Monad.ST`,+   `Control.Monad.ST.Lazy`, `Foreign.ForeignPtr`, and `Foreign.Marshal`)+ - Backport `forkFinally` and `forkOSWithUnmask` to `Control.Concurrent.Compat`+ - Backport `Data.Functor.Const`+ - Backport `modifyIORef'`, `atomicModifyIORef'` and `atomicWriteIORef` to+   `Data.IORef.Compat`+ - `Data.Ratio.{denominator,numerator}` have no `Integral` constraint anymore+ - Backport `modifySTRef'` to `Data.STRef.Compat`+ - Export `String`, `lines`, `words`, `unlines`, and `unwords` to+   `Data.String.Compat`+ - Generalize `Debug.Trace.{traceM, traceShowM}` from `Monad` to `Applicative`+ - Backport `errorWithoutStackTrace` to `Prelude.Compat`+ - Backport `unsafeFixIO` and `unsafeDupablePerformIO` to+   `System.IO.Unsafe.Compat`+ ## Changes in 0.8.2  - Backport `bitDefault`, `testBitDefault`, and `popCountDefault` in    `Data.Bits.Compat` to all versions of `base`
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2012-2015 Simon Hengel <sol@typeful.net> and Ryan Scott <ryan.gl.scott@ku.edu>+Copyright (c) 2012-2015 Simon Hengel <sol@typeful.net> and Ryan Scott <ryan.gl.scott@gmail.com>  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal
README.markdown view
@@ -1,4 +1,20 @@-# A compatibility layer for `base` [![Hackage version](https://img.shields.io/hackage/v/base-compat.svg?style=flat)](http://hackage.haskell.org/package/base-compat) [![Build Status](https://img.shields.io/travis/haskell-compat/base-compat.svg?style=flat)](https://travis-ci.org/haskell-compat/base-compat)+# A compatibility layer for `base`+[![Hackage](https://img.shields.io/hackage/v/base-compat.svg)][Hackage: base-compat]+[![Hackage Dependencies](https://img.shields.io/hackage-deps/v/base-compat.svg)](http://packdeps.haskellers.com/reverse/base-compat)+[![Haskell Programming Language](https://img.shields.io/badge/language-Haskell-blue.svg)][Haskell.org]+[![BSD3 License](http://img.shields.io/badge/license-MIT-brightgreen.svg)][tl;dr Legal: MIT]+[![Build](https://img.shields.io/travis/haskell-compat/base-compat.svg)](https://travis-ci.org/haskell-compat/base-compat)++[Hackage: base-compat]:+  http://hackage.haskell.org/package/base-compat+  "base-compat package on Hackage"+[Haskell.org]:+  http://www.haskell.org+  "The Haskell Programming Language"+[tl;dr Legal: MIT]:+  https://tldrlegal.com/license/mit-license+  "MIT License"+ ## Scope  The scope of `base-compat` is to provide functions available in later versions@@ -12,13 +28,19 @@ package [`base-orphans`](https://github.com/haskell-compat/base-orphans) for that. +In addition, `base-compat` only backports functions. In particular, we+purposefully do not backport data types or type classes introduced in newer+versions of `base`. For more info, see the+[Data types and type classes](#data-types-and-type-classes)+section.+ ## Basic usage  In your cabal file, you should have something like this:  ```   build-depends:      base              >= 4.3-                    , base-compat       >= 0.8.0+                    , base-compat       >= 0.9.0 ```  Then, lets say you want to use the `isRight` function introduced with@@ -83,7 +105,7 @@ ### For compatibility with the latest released version of `base`   * `Prelude.Compat` incorporates the AMP/Foldable/Traversable changes and-   exposes the same interface as `Prelude` from `base-4.8.0.0`+   exposes the same interface as `Prelude` from `base-4.9.0.0`  * `System.IO.Error.catch` is not re-exported from `Prelude.Compat` for older    versions of `base`  * `Text.Read.Compat.readMaybe`@@ -93,13 +115,19 @@  * Added `toIntegralSized` to `Data.Bits.Compat` (if using `base-4.7`)  * Added `bool` function to `Data.Bool.Compat`  * Added `isLeft` and `isRight` to `Data.Either.Compat`+ * Added `forkFinally` to `Control.Concurrent.Compat`  * Added `withMVarMasked` function to `Control.Concurrent.MVar.Compat`  * Added `(<$!>)` function to `Control.Monad.Compat`+ * Weakened `RealFloat` constraints on `realPart`, `imagPart`, `conjugate`, `mkPolar`,+   and `cis` in `Data.Complex.Compat`  * Added `($>)` and `void` functions to `Data.Functor.Compat`  * `(&)` function to `Data.Function.Compat`  * `($>)` and `void` functions to `Data.Functor.Compat`+ * `modifyIORef'`, `atomicModifyIORef'` and `atomicWriteIORef` to `Data.IORef.Compat`  * `dropWhileEnd`, `isSubsequenceOf`, `sortOn`, and `uncons` functions to `Data.List.Compat`  * Correct versions of `nub`, `nubBy`, `union`, and `unionBy` to `Data.List.Compat`+ * `modifySTRef'` to `Data.STRef.Compat`+ * `String`, `lines`, `words`, `unlines`, and `unwords` to `Data.String.Compat`  * `makeVersion` function to `Data.Version.Compat`  * `traceId`, `traceShowId`, `traceM`, and `traceShowM` functions to `Debug.Trace.Compat`  * `byteSwap16`, `byteSwap32`, and `byteSwap64` to `Data.Word.Compat`@@ -109,9 +137,114 @@  * Added `Data.List.Compat.scanl'`  * `showFFloatAlt` and `showGFloatAlt` to `Numeric.Compat`  * `lookupEnv`, `setEnv` and `unsetEnv` to `System.Environment.Compat`+ * `unsafeFixIO` and `unsafeDupablePerformIO` to `System.IO.Unsafe.IO` -## Supported versions of GHC/base+## What is not covered +### Data types and type classes+`base-compat` purposefully does not export any data types or type classes that+were introduced in more recent versions of `base`. The main reasoning for this+policy is that it is not some data types and type classes have had their APIs+change in different versions of `base`, which makes having a consistent+compatibility API for them practically impossible.++As an example, consider the `FiniteBits` type class. It was introduced in+[`base-4.7.0.0`](http://hackage.haskell.org/package/base-4.7.0.0/docs/Data-Bits.html#t:FiniteBits)+with the following API:++```haskell+class Bits b => FiniteBits b where+    finiteBitSize :: b -> Int+```++However, in [`base-4.8.0.0`](http://hackage.haskell.org/package/base-4.8.0.0/docs/Data-Bits.html#t:FiniteBits),+`FiniteBits` gained additional functions:++```haskell+class Bits b => FiniteBits b where+    finiteBitSize :: b -> Int+    countLeadingZeros :: b -> Int+    countTrailingZeros :: b -> Int+```++This raises the question: how can `FiniteBits` be backported consistently+across all versions of `base`? One approach is to backport the API exposed in+`base-4.8.0.0` on versions prior to `4.7.0.0`. The problem with this is that+`countLeadingZeros` and `countTrailingZeros` are not exposed in `base-4.7.0.0`,+so instances of `FiniteBits` would have to be declared like this:++```haskell+instance FiniteBits Foo where+    finiteBitSize = ...+#if MIN_VERSION_base(4,8,0) || !(MIN_VERSION_base(4,7,0))+    countLeadingZeros = ...+    countTrailingZeros = ...+#endif+```++This is a very unsatisfactory solution, and for this reason, we do not pursue+it. For similar reasons, we do not backport data types.++### Other compatibility packages++If you _really_ need your favorite data type or type class in `base` to be+backported, you might be in luck, since several data types have their own+compatibility packages on Hackage. Here is a list of such packages:++* [`bifunctors`](http://hackage.haskell.org/package/bifunctors)+  for the [`Bifunctor`](http://hackage.haskell.org/package/base-4.8.0.0/docs/Data-Bifunctor.html#t:Bifunctor)+  type class, introduced in `base-4.8.0.0`+* [`generic-deriving`](http://hackage.haskell.org/package/generic-deriving)+  for everything in the [`GHC.Generics`](http://hackage.haskell.org/package/base-4.8.0.0/docs/GHC-Generics.html)+  module, introduced to `ghc-prim` in GHC 7.2 (and later moved to `base-4.6.0.0`)+* [`nats`](http://hackage.haskell.org/package/nats)+  for the [`Natural`](http://hackage.haskell.org/package/base-4.8.0.0/docs/Numeric-Natural.html)+  data type, introduced in `base-4.8.0.0`+* [`semigroups`](http://hackage.haskell.org/package/semigroups)+  for the [`Semigroup`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Semigroup.html#t:Semigroup)+  typeclass and the+  [`NonEmpty`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-List-NonEmpty.html#t:NonEmpty),+  [`Min`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Semigroup.html#t:Min),+  [`Max`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Semigroup.html#t:Max),+  [`First`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Semigroup.html#t:First),+  [`Last`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Semigroup.html#t:Last),+  [`WrappedMonoid`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Semigroup.html#t:WrappedMonoid),+  [`Option`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Semigroup.html#t:Option),+  and+  [`Arg`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Semigroup.html#t:Arg)+  data types, introduced in `base-4.9.0.0`+* [`tagged`](http://hackage.haskell.org/package/tagged)+  for the [`Proxy`](http://hackage.haskell.org/package/base-4.7.0.0/docs/Data-Proxy.html#t:Proxy)+  data type, introduced in `base-4.7.0.0`+* [`transformers`](http://hackage.haskell.org/package/transformers)+  for:+  * The [`Identity`](http://hackage.haskell.org/package/base-4.8.0.0/docs/Data-Functor-Identity.html#t:Identity)+    data type, introduced in `base-4.8.0.0`+  * The [`MonadIO`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Control-Monad-IO-Class.html#t:MonadIO),+    [`Eq1`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor-Classes.html#t:Eq1),+    [`Eq2`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor-Classes.html#t:Eq2),+    [`Ord1`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor-Classes.html#t:Ord1),+    [`Ord2`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor-Classes.html#t:Ord2),+    [`Read1`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor-Classes.html#t:Read1),+    [`Read2`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor-Classes.html#t:Read2),+    [`Show1`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor-Classes.html#t:Show1),+    and+    [`Show2`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor-Classes.html#t:Show2)+    typeclasses; and the+    [`Compose`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor-Compose.html#t:Compose),+    [`Product`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor-Product.html#t:Product),+    and+    [`Sum`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor-Sum.html#t:Sum)+    data types, introduced in `base-4.9.0.0`+* [`void`](http://hackage.haskell.org/package/void)+  for the [`Void`](http://hackage.haskell.org/package/base-4.8.0.0/docs/Data-Void.html#t:Void)+  data type, introduced in `base-4.8.0.0`++## Supported versions of GHC/`base`++ * `ghc-8.0.1`  / `base-4.9.0.0`+ * `ghc-7.10.3` / `base-4.8.2.0`+ * `ghc-7.10.2` / `base-4.8.1.0`  * `ghc-7.10.1` / `base-4.8.0.0`  * `ghc-7.8.4`  / `base-4.7.0.2`  * `ghc-7.8.3`  / `base-4.7.0.1`@@ -129,16 +262,8 @@  * `ghc-7.0.2`  / `base-4.3.1.0`  * `ghc-7.0.1`  / `base-4.3.0.0` -Patches are welcome; add tests for new code!--## Development--For `Prelude.Compat` there is an `Prelude.index` file that was generated from-the output of--    ghc --show-iface Prelude.hi--To verify that `Prelude.Compat` matches the specification given in-`Prelude.types` run:+We also make an attempt to keep `base-compat` building with GHC HEAD, but due+to its volatility, it may not work at any given point in time. If it doesn't,+please report it! -    ./check-Prelude.sh+Patches are welcome; add tests for new code!
base-compat.cabal view
@@ -1,5 +1,5 @@ name:             base-compat-version:          0.8.2+version:          0.9.0 license:          MIT license-file:     LICENSE copyright:        (c) 2012-2015 Simon Hengel,@@ -7,10 +7,10 @@                   (c) 2015 Ryan Scott author:           Simon Hengel <sol@typeful.net>,                   João Cristóvão <jmacristovao@gmail.com>,-                  Ryan Scott <ryan.gl.scott@ku.edu>+                  Ryan Scott <ryan.gl.scott@gmail.com> maintainer:       Simon Hengel <sol@typeful.net>,                   João Cristóvão <jmacristovao@gmail.com>,-                  Ryan Scott <ryan.gl.scott@ku.edu>+                  Ryan Scott <ryan.gl.scott@gmail.com> build-type:       Simple cabal-version:    >= 1.8 category:         Compatibility@@ -24,9 +24,20 @@                   for recent changes.                   .                   Note that @base-compat@ does not add any orphan instances.-                  There is a separate package-                  @<http://hackage.haskell.org/package/base-orphans base-orphans>@+                  There is a separate package,+                  @<http://hackage.haskell.org/package/base-orphans base-orphans>@,                   for that.+                  .+                  In addition, `base-compat` does not backport any data types+                  or type classes. See+                  @<https://github.com/haskell-compat/base-compat#data-types-and-type-classes this section of the README>@+                  for more info.+tested-with:        GHC == 7.0.1,  GHC == 7.0.2,  GHC == 7.0.3,  GHC == 7.0.4+                  , GHC == 7.2.1,  GHC == 7.2.2+                  , GHC == 7.4.1,  GHC == 7.4.2+                  , GHC == 7.6.1,  GHC == 7.6.2,  GHC == 7.6.3+                  , GHC == 7.8.1,  GHC == 7.8.2,  GHC == 7.8.3,  GHC == 7.8.4+                  , GHC == 7.10.1, GHC == 7.10.2, GHC == 7.10.3 extra-source-files: CHANGES.markdown, README.markdown  source-repository head@@ -47,28 +58,42 @@       src    exposed-modules:+      Control.Concurrent.Compat       Control.Concurrent.MVar.Compat       Control.Monad.Compat+      Control.Monad.ST.Lazy.Unsafe.Compat+      Control.Monad.ST.Unsafe.Compat       Data.Bits.Compat       Data.Bool.Compat+      Data.Complex.Compat       Data.Either.Compat       Data.Foldable.Compat       Data.Function.Compat       Data.Functor.Compat+      Data.Functor.Const.Compat+      Data.IORef.Compat       Data.List.Compat       Data.Monoid.Compat+      Data.Ratio.Compat+      Data.STRef.Compat+      Data.String.Compat       Data.Version.Compat       Data.Word.Compat       Debug.Trace.Compat       Foreign.Compat+      Foreign.ForeignPtr.Safe.Compat+      Foreign.ForeignPtr.Unsafe.Compat       Foreign.Marshal.Alloc.Compat       Foreign.Marshal.Array.Compat       Foreign.Marshal.Compat+      Foreign.Marshal.Safe.Compat+      Foreign.Marshal.Unsafe.Compat       Foreign.Marshal.Utils.Compat       Numeric.Compat       Prelude.Compat       System.Environment.Compat       System.Exit.Compat+      System.IO.Unsafe.Compat       Text.Read.Compat  test-suite spec@@ -80,6 +105,24 @@       test   main-is:       Spec.hs+  other-modules:+      Control.Monad.CompatSpec+      Data.Bits.CompatSpec+      Data.Bool.CompatSpec+      Data.Either.CompatSpec+      Data.Function.CompatSpec+      Data.Functor.CompatSpec+      Data.IORef.CompatSpec+      Data.List.CompatSpec+      Data.Monoid.CompatSpec+      Data.STRef.CompatSpec+      Data.Version.CompatSpec+      Data.Word.CompatSpec+      Foreign.Marshal.Alloc.CompatSpec+      Foreign.Marshal.Utils.CompatSpec+      Numeric.CompatSpec+      System.Environment.CompatSpec+      Text.Read.CompatSpec   build-depends:       base >= 4.3 && < 5     , base-compat
+ src/Control/Concurrent/Compat.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE CPP, NoImplicitPrelude #-}+{-# LANGUAGE RankNTypes #-}+module Control.Concurrent.Compat (+  module Base+, forkFinally+, forkOSWithUnmask+) where++import Control.Concurrent as Base++#if !(MIN_VERSION_base(4,6,0))+import Control.Exception+#endif++#if !(MIN_VERSION_base(4,9,0))+import GHC.IO (unsafeUnmask)+import Prelude+#endif++#if !(MIN_VERSION_base(4,6,0))+-- | fork a thread and call the supplied function when the thread is about+-- to terminate, with an exception or a returned value.  The function is+-- called with asynchronous exceptions masked.+--+-- > forkFinally action and_then =+-- >   mask $ \restore ->+-- >     forkIO $ try (restore action) >>= and_then+--+-- This function is useful for informing the parent when a child+-- terminates, for example.+--+-- /Since: 4.6.0.0/+forkFinally :: IO a -> (Either SomeException a -> IO ()) -> IO ThreadId+forkFinally action and_then =+  mask $ \restore ->+    forkIO $ try (restore action) >>= and_then+#endif++#if !(MIN_VERSION_base(4,9,0))+-- | Like 'forkIOWithUnmask', but the child thread is a bound thread,+-- as with 'forkOS'.+forkOSWithUnmask :: ((forall a . IO a -> IO a) -> IO ()) -> IO ThreadId+forkOSWithUnmask io = forkOS (io unsafeUnmask)+#endif
src/Control/Monad/Compat.hs view
@@ -19,13 +19,30 @@  , (<$!>) #endif+#if !(MIN_VERSION_base(4,9,0))+, forever+, filterM+, mapAndUnzipM+, zipWithM+, zipWithM_+, replicateM+, replicateM_+#endif ) where -#if MIN_VERSION_base(4,8,0)+#if MIN_VERSION_base(4,9,0) import Control.Monad as Base #else import Control.Monad as Base hiding (-    foldM+    forever+  , filterM+  , mapAndUnzipM+  , zipWithM+  , zipWithM_+  , replicateM+  , replicateM_+# if !(MIN_VERSION_base(4,8,0))+  , foldM   , foldM_   , forM   , forM_@@ -37,8 +54,9 @@   , sequence_   , unless   , when+# endif   )-import Control.Applicative (Alternative(..))+import Control.Applicative import Data.Foldable.Compat import Data.Traversable import Prelude.Compat@@ -115,4 +133,52 @@   x <- m   let z = f x   z `seq` return z+#endif++#if !(MIN_VERSION_base(4,9,0))+-- | @'forever' act@ repeats the action infinitely.+forever     :: (Applicative f) => f a -> f b+{-# INLINE forever #-}+forever a   = let a' = a *> a' in a'+-- Use explicit sharing here, as it is prevents a space leak regardless of+-- optimizations.++-- | This generalizes the list-based 'filter' function.+{-# INLINE filterM #-}+filterM          :: (Applicative m) => (a -> m Bool) -> [a] -> m [a]+filterM p        = foldr (\ x -> liftA2 (\ flg -> if flg then (x:) else id) (p x)) (pure [])++-- | The 'mapAndUnzipM' function maps its first argument over a list, returning+-- the result as a pair of lists. This function is mainly used with complicated+-- data structures or a state-transforming monad.+mapAndUnzipM      :: (Applicative m) => (a -> m (b,c)) -> [a] -> m ([b], [c])+{-# INLINE mapAndUnzipM #-}+mapAndUnzipM f xs =  unzip <$> traverse f xs++-- | The 'zipWithM' function generalizes 'zipWith' to arbitrary applicative functors.+zipWithM          :: (Applicative m) => (a -> b -> m c) -> [a] -> [b] -> m [c]+{-# INLINE zipWithM #-}+zipWithM f xs ys  =  sequenceA (zipWith f xs ys)++-- | 'zipWithM_' is the extension of 'zipWithM' which ignores the final result.+zipWithM_         :: (Applicative m) => (a -> b -> m c) -> [a] -> [b] -> m ()+{-# INLINE zipWithM_ #-}+zipWithM_ f xs ys =  sequenceA_ (zipWith f xs ys)++-- | @'replicateM' n act@ performs the action @n@ times,+-- gathering the results.+replicateM        :: (Applicative m) => Int -> m a -> m [a]+{-# INLINEABLE replicateM #-}+{-# SPECIALISE replicateM :: Int -> IO a -> IO [a] #-}+{-# SPECIALISE replicateM :: Int -> Maybe a -> Maybe [a] #-}+replicateM 0 _    = pure []+replicateM n x    = liftA2 (:) x (replicateM (pred n) x)++-- | Like 'replicateM', but discards the result.+replicateM_       :: (Applicative m) => Int -> m a -> m ()+{-# INLINEABLE replicateM_ #-}+{-# SPECIALISE replicateM_ :: Int -> IO a -> IO () #-}+{-# SPECIALISE replicateM_ :: Int -> Maybe a -> Maybe () #-}+replicateM_ 0 _   = pure ()+replicateM_ n x   = x *> replicateM_ (pred n) x #endif
+ src/Control/Monad/ST/Lazy/Unsafe/Compat.hs view
@@ -0,0 +1,12 @@+{-# LANGUAGE CPP, NoImplicitPrelude #-}+module Control.Monad.ST.Lazy.Unsafe.Compat (+  -- * Unsafe operations+  unsafeInterleaveST+, unsafeIOToST+) where++#if MIN_VERSION_base(4,6,0)+import Control.Monad.ST.Lazy.Unsafe (unsafeInterleaveST, unsafeIOToST)+#else+import Control.Monad.ST.Lazy (unsafeInterleaveST, unsafeIOToST)+#endif
+ src/Control/Monad/ST/Unsafe/Compat.hs view
@@ -0,0 +1,13 @@+{-# LANGUAGE CPP, NoImplicitPrelude #-}+module Control.Monad.ST.Unsafe.Compat (+  -- * Unsafe operations+  unsafeInterleaveST+, unsafeIOToST+, unsafeSTToIO+) where++#if MIN_VERSION_base(4,6,0)+import Control.Monad.ST.Unsafe (unsafeInterleaveST, unsafeIOToST, unsafeSTToIO)+#else+import Control.Monad.ST (unsafeInterleaveST, unsafeIOToST, unsafeSTToIO)+#endif
+ src/Data/Complex/Compat.hs view
@@ -0,0 +1,50 @@+{-# LANGUAGE CPP, NoImplicitPrelude #-}+module Data.Complex.Compat (+  module Base+#if MIN_VERSION_base(4,4,0) && !(MIN_VERSION_base(4,8,0))+, realPart+, imagPart+, mkPolar+, cis+, conjugate+#endif+) where++#if !(MIN_VERSION_base(4,4,0)) || MIN_VERSION_base(4,8,0)+import Data.Complex as Base+#else+import Data.Complex as Base hiding (+    realPart+  , imagPart+  , mkPolar+  , cis+  , conjugate+  )+import Prelude+#endif++#if MIN_VERSION_base(4,4,0) && !(MIN_VERSION_base(4,8,0))+-- | Extracts the real part of a complex number.+realPart :: Complex a -> a+realPart (x :+ _) =  x++-- | Extracts the imaginary part of a complex number.+imagPart :: Complex a -> a+imagPart (_ :+ y) =  y++-- | The conjugate of a complex number.+{-# SPECIALISE conjugate :: Complex Double -> Complex Double #-}+conjugate        :: Num a => Complex a -> Complex a+conjugate (x:+y) =  x :+ (-y)++-- | Form a complex number from polar components of magnitude and phase.+{-# SPECIALISE mkPolar :: Double -> Double -> Complex Double #-}+mkPolar          :: Floating a => a -> a -> Complex a+mkPolar r theta  =  r * cos theta :+ r * sin theta++-- | @'cis' t@ is a complex value with magnitude @1@+-- and phase @t@ (modulo @2*'pi'@).+{-# SPECIALISE cis :: Double -> Complex Double #-}+cis              :: Floating a => a -> Complex a+cis theta        =  cos theta :+ sin theta+#endif
+ src/Data/Functor/Const/Compat.hs view
@@ -0,0 +1,4 @@+{-# LANGUAGE CPP, NoImplicitPrelude #-}+module Data.Functor.Const.Compat (Const(..)) where++import Control.Applicative (Const(..))
+ src/Data/IORef/Compat.hs view
@@ -0,0 +1,42 @@+{-# LANGUAGE CPP, NoImplicitPrelude #-}+module Data.IORef.Compat (+  module Base+, modifyIORef'+, atomicModifyIORef'+, atomicWriteIORef+) where++import Data.IORef as Base++#if !(MIN_VERSION_base(4,6,0))+import Prelude++-- |Strict version of 'modifyIORef'+--+-- /Since: 4.6.0.0/+modifyIORef' :: IORef a -> (a -> a) -> IO ()+modifyIORef' ref f = do+    x <- readIORef ref+    let x' = f x+    x' `seq` writeIORef ref x'++-- | Strict version of 'atomicModifyIORef'.  This forces both the value stored+-- in the 'IORef' as well as the value returned.+--+-- /Since: 4.6.0.0/+atomicModifyIORef' :: IORef a -> (a -> (a,b)) -> IO b+atomicModifyIORef' ref f = do+    b <- atomicModifyIORef ref $ \a ->+            case f a of+                v@(a',_) -> a' `seq` v+    b `seq` return b++-- | Variant of 'writeIORef' with the \"barrier to reordering\" property that+-- 'atomicModifyIORef' has.+--+-- /Since: 4.6.0.0/+atomicWriteIORef :: IORef a -> a -> IO ()+atomicWriteIORef ref a = do+    x <- atomicModifyIORef ref (\_ -> (a, ()))+    x `seq` return ()+#endif
+ src/Data/Ratio/Compat.hs view
@@ -0,0 +1,32 @@+{-# LANGUAGE CPP, NoImplicitPrelude #-}+module Data.Ratio.Compat (+  module Base+#if MIN_VERSION_base(4,4,0) && !(MIN_VERSION_base(4,9,0))+, denominator+, numerator+#endif+) where++#if !(MIN_VERSION_base(4,4,0)) || MIN_VERSION_base(4,9,0)+import Data.Ratio as Base+#else+import Data.Ratio as Base hiding (+    denominator+  , numerator+  )+import GHC.Real (Ratio(..))+#endif++#if MIN_VERSION_base(4,4,0) && !(MIN_VERSION_base(4,9,0))+-- | Extract the numerator of the ratio in reduced form:+-- the numerator and denominator have no common factor and the denominator+-- is positive.+numerator :: Ratio a -> a+numerator (x :% _) = x++-- | Extract the denominator of the ratio in reduced form:+-- the numerator and denominator have no common factor and the denominator+-- is positive.+denominator :: Ratio a -> a+denominator (_ :% y) =  y+#endif
+ src/Data/STRef/Compat.hs view
@@ -0,0 +1,21 @@+{-# LANGUAGE CPP, NoImplicitPrelude #-}+module Data.STRef.Compat (+  module Base+, modifySTRef'+) where++import Data.STRef as Base++#if !(MIN_VERSION_base(4,6,0))+import Control.Monad.ST (ST)+import Prelude (seq)++-- | Strict version of 'modifySTRef'+--+-- /Since: 4.6.0.0/+modifySTRef' :: STRef s a -> (a -> a) -> ST s ()+modifySTRef' ref f = do+    x <- readSTRef ref+    let x' = f x+    x' `seq` writeSTRef ref x'+#endif
+ src/Data/String/Compat.hs view
@@ -0,0 +1,15 @@+{-# LANGUAGE CPP, NoImplicitPrelude #-}+module Data.String.Compat (+  module Base+, String+, lines+, words+, unlines+, unwords+) where++import Data.String as Base++#if !(MIN_VERSION_base(4,4,0))+import Prelude (String, lines, words, unlines, unwords)+#endif
src/Debug/Trace/Compat.hs view
@@ -6,11 +6,21 @@ , traceM , traceShowM ) where++#if !(MIN_VERSION_base(4,7,0)) || MIN_VERSION_base(4,9,0) import Debug.Trace as Base+#else+import Debug.Trace as Base hiding (+    traceM+  , traceShowM+  )+#endif -#if !(MIN_VERSION_base(4,7,0))+#if !(MIN_VERSION_base(4,9,0)) import Prelude.Compat+#endif +#if !(MIN_VERSION_base(4,7,0)) {-| Like 'trace' but returns the message instead of a third value. @@ -26,12 +36,20 @@ -} traceShowId :: (Show a) => a -> a traceShowId a = trace (show a) a+#endif +#if !(MIN_VERSION_base(4,9,0)) {-|-Like 'trace' but returning unit in an arbitrary monad. Allows for convenient-use in do-notation. Note that the application of 'trace' is not an action in the-monad, as 'traceIO' is in the 'IO' monad.+Like 'trace' but returning unit in an arbitrary 'Applicative' context. Allows+for convenient use in do-notation. +Note that the application of 'traceM' is not an action in the 'Applicative'+context, as 'traceIO' is in the 'IO' type. While the fresh bindings in the+following example will force the 'traceM' expressions to be reduced every time+the @do@-block is executed, @traceM "not crashed"@ would only be reduced once,+and the message would only be printed once.  If your monad is in 'MonadIO',+@liftIO . traceIO@ may be a better option.+ > ... = do >   x <- ... >   traceM $ "x: " ++ show x@@ -40,20 +58,20 @@  /Since: 4.7.0.0/ -}-traceM :: (Monad m) => String -> m ()-traceM string = trace string $ return ()+traceM :: (Applicative f) => String -> f ()+traceM string = trace string $ pure ()  {-| Like 'traceM', but uses 'show' on the argument to convert it to a 'String'.  > ... = do >   x <- ...->   traceMShow $ x+>   traceShowM $ x >   y <- ...->   traceMShow $ x + y+>   traceShowM $ x + y  /Since: 4.7.0.0/ -}-traceShowM :: (Show a, Monad m) => a -> m ()+traceShowM :: (Show a, Applicative f) => a -> f () traceShowM = traceM . show #endif
+ src/Foreign/ForeignPtr/Safe/Compat.hs view
@@ -0,0 +1,34 @@+{-# LANGUAGE CPP, NoImplicitPrelude #-}+module Foreign.ForeignPtr.Safe.Compat (+        -- * Finalised data pointers+          ForeignPtr+        , FinalizerPtr+#if defined(__HUGS__) || defined(__GLASGOW_HASKELL__)+        , FinalizerEnvPtr+#endif+        -- ** Basic operations+        , newForeignPtr+        , newForeignPtr_+        , addForeignPtrFinalizer+#if defined(__HUGS__) || defined(__GLASGOW_HASKELL__)+        , newForeignPtrEnv+        , addForeignPtrFinalizerEnv+#endif+        , withForeignPtr++#ifdef __GLASGOW_HASKELL__+        , finalizeForeignPtr+#endif++        -- ** Low-level operations+        , touchForeignPtr+        , castForeignPtr++        -- ** Allocating managed memory+        , mallocForeignPtr+        , mallocForeignPtrBytes+        , mallocForeignPtrArray+        , mallocForeignPtrArray0+    ) where++import Foreign.ForeignPtr
+ src/Foreign/ForeignPtr/Unsafe/Compat.hs view
@@ -0,0 +1,11 @@+{-# LANGUAGE CPP, NoImplicitPrelude #-}+module Foreign.ForeignPtr.Unsafe.Compat (+  -- ** Unsafe low-level operations+  unsafeForeignPtrToPtr+) where++#if MIN_VERSION_base(4,6,0)+import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)+#else+import Foreign.ForeignPtr (unsafeForeignPtrToPtr)+#endif
+ src/Foreign/Marshal/Safe/Compat.hs view
@@ -0,0 +1,16 @@+{-# LANGUAGE CPP, NoImplicitPrelude #-}+module Foreign.Marshal.Safe.Compat (+         -- | The module "Foreign.Marshal.Safe" re-exports the other modules in the+         -- @Foreign.Marshal@ hierarchy:+          module Foreign.Marshal.Alloc+        , module Foreign.Marshal.Array+        , module Foreign.Marshal.Error+        , module Foreign.Marshal.Pool+        , module Foreign.Marshal.Utils+        ) where++import Foreign.Marshal.Alloc+import Foreign.Marshal.Array+import Foreign.Marshal.Error+import Foreign.Marshal.Pool+import Foreign.Marshal.Utils
+ src/Foreign/Marshal/Unsafe/Compat.hs view
@@ -0,0 +1,11 @@+{-# LANGUAGE CPP, NoImplicitPrelude #-}+module Foreign.Marshal.Unsafe.Compat (+  -- * Unsafe functions+  unsafeLocalState+) where++#if MIN_VERSION_base(4,6,0)+import Foreign.Marshal.Unsafe (unsafeLocalState)+#else+import Foreign.Marshal (unsafeLocalState)+#endif
src/Prelude/Compat.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE CPP, NoImplicitPrelude #-} module Prelude.Compat (-#if MIN_VERSION_base(4,8,0)+#if MIN_VERSION_base(4,9,0)   module Base #else   either@@ -101,6 +101,7 @@ , (||) , ($) , error+, errorWithoutStackTrace , undefined , seq @@ -257,7 +258,7 @@ ) where  -#if MIN_VERSION_base(4,8,0)+#if MIN_VERSION_base(4,9,0)  import Prelude as Base @@ -290,9 +291,21 @@   , sum   ) -import Data.Word import Data.Foldable.Compat import Data.Traversable-import Data.Monoid++# if !(MIN_VERSION_base(4,8,0)) import Control.Applicative+import Data.Monoid+import Data.Word+# endif+#endif++#if !(MIN_VERSION_base(4,9,0))+-- | A variant of 'error' that does not produce a stack trace.+--+-- /Since: 4.9.0.0/+errorWithoutStackTrace :: [Char] -> a+errorWithoutStackTrace s = error s+{-# NOINLINE errorWithoutStackTrace #-} #endif
+ src/System/IO/Unsafe/Compat.hs view
@@ -0,0 +1,35 @@+{-# LANGUAGE CPP, NoImplicitPrelude #-}+module System.IO.Unsafe.Compat (+  module Base+, unsafeFixIO+, unsafeDupablePerformIO+) where++import System.IO.Unsafe as Base++#if !(MIN_VERSION_base(4,5,0))+import Control.Exception+import Data.IORef+import GHC.Base+import GHC.IO++-- | A slightly faster version of `System.IO.fixIO` that may not be+-- safe to use with multiple threads.  The unsafety arises when used+-- like this:+--+-- >  unsafeFixIO $ \r -> do+-- >     forkIO (print r)+-- >     return (...)+--+-- In this case, the child thread will receive a @NonTermination@+-- exception instead of waiting for the value of @r@ to be computed.+--+-- /Since: 4.5.0.0/+unsafeFixIO :: (a -> IO a) -> IO a+unsafeFixIO k = do+  ref <- newIORef (throw NonTermination)+  ans <- unsafeDupableInterleaveIO (readIORef ref)+  result <- k ans+  writeIORef ref result+  return result+#endif
+ test/Control/Monad/CompatSpec.hs view
@@ -0,0 +1,16 @@+module Control.Monad.CompatSpec (main, spec) where++import           Test.Hspec++import           Control.Monad.Compat+import           Prelude ()+import           Prelude.Compat++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+  describe "(<$!>)" $ do+    it "is a strict version of (<$>)" $ do+      not <$!> [True, False] `shouldBe` not <$> [True, False]
+ test/Data/Bits/CompatSpec.hs view
@@ -0,0 +1,34 @@+{-# LANGUAGE CPP #-}+module Data.Bits.CompatSpec (main, spec) where++import Test.Hspec+import Data.Bits.Compat++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+  describe "bitDefault" $+    it "sets the ith bit with all other bits clear" $ do+      bitDefault 0 `shouldBe` (1 :: Int)+      bitDefault 1 `shouldBe` (2 :: Int)+      bitDefault 2 `shouldBe` (4 :: Int)+      bitDefault 3 `shouldBe` (8 :: Int)+  describe "testBitDefault" $+    it "returns True if the nth bit of the argument is 1" $ do+      testBitDefault (10 :: Int) 0 `shouldBe` False+      testBitDefault (10 :: Int) 1 `shouldBe` True+      testBitDefault (10 :: Int) 2 `shouldBe` False+      testBitDefault (10 :: Int) 3 `shouldBe` True+  describe "popCountDefault" $+    it "returns the number of set bits in the argument" $ do+      popCountDefault (0  :: Int) `shouldBe` 0+      popCountDefault (1  :: Int) `shouldBe` 1+      popCountDefault (10 :: Int) `shouldBe` 2+#if MIN_VERSION_base(4,7,0)+  describe "toIntegralSized" $+    it "converts an Integral type to another as measured by bitSizeMaybe" $ do+      toIntegralSized (42 :: Integer)                   `shouldBe` (Just 42 :: Maybe Int)+      toIntegralSized (12345678901234567890 :: Integer) `shouldBe` (Nothing :: Maybe Int)+#endif
+ test/Data/Bool/CompatSpec.hs view
@@ -0,0 +1,18 @@+module Data.Bool.CompatSpec (main, spec) where++import           Test.Hspec++import           Data.Bool.Compat++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+  describe "bool" $ do+    it "evaluates to first parameter if condition is False" $ do+      bool "KO" "OK" False `shouldBe` "KO"++    it "evaluates to second parameter if condition is True" $ do+      bool "KO" "OK" True `shouldBe` "OK"+
+ test/Data/Either/CompatSpec.hs view
@@ -0,0 +1,25 @@+module Data.Either.CompatSpec (main, spec) where++import           Test.Hspec++import           Data.Either.Compat++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+  describe "isLeft" $ do+    it "returns True for a Left value" $ do+      isLeft (Left "23" :: Either String String) `shouldBe` True++    it "returns False for a Right value" $ do+      isLeft (Right "23" :: Either String String) `shouldBe` False++  describe "isRight" $ do+    it "returns False for a Left value" $ do+      isRight (Left "23" :: Either String String) `shouldBe` False++    it "returns True for a Right value" $ do+      isRight (Right "23" :: Either String String) `shouldBe` True+
+ test/Data/Function/CompatSpec.hs view
@@ -0,0 +1,13 @@+module Data.Function.CompatSpec (main, spec) where++import           Test.Hspec+import           Data.Function.Compat++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+  describe "&" $ do+    it "reverses function application" $ do+      (False & not) `shouldBe` True
+ test/Data/Functor/CompatSpec.hs view
@@ -0,0 +1,17 @@+module Data.Functor.CompatSpec (main, spec) where++import           Test.Hspec+import           Data.Functor.Compat++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+  describe "void" $ do+    it "discards computation result" $ do+      void (return 1 :: IO Int) `shouldReturn` ()++  describe "$>" $ do+    it "is the same as flipped <$" $ do+      (Just 5 :: Maybe Int) $> 6 `shouldBe` (Just 6 :: Maybe Int)
+ test/Data/IORef/CompatSpec.hs view
@@ -0,0 +1,22 @@+module Data.IORef.CompatSpec (main, spec) where++import           Test.Hspec++import           Control.Monad+import           Data.IORef.Compat++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+  describe "modifyIORef'" $+    it "mutates the contents of an IORef strictly" $ do+      ref <- newIORef 0+      replicateM_ 1000000 $ modifyIORef' ref (+1)+      readIORef ref `shouldReturn` (1000000 :: Int)+  describe "atomicModifyIORef'" $+    it "atomically modifies the contents of an IORef strictly" $ do+      ref <- newIORef 0+      replicateM_ 1000000 . atomicModifyIORef' ref $ \n -> (n+1, ())+      readIORef ref `shouldReturn` (1000000 :: Int)
+ test/Data/List/CompatSpec.hs view
@@ -0,0 +1,43 @@+module Data.List.CompatSpec (main, spec) where++import           Test.Hspec+import           Data.List.Compat++data Asymmetric = A | B deriving Show++instance Eq Asymmetric where+  A == _ = True+  B == _ = False++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+  describe "dropWhileEnd" $ do+    it "drops the largest suffix of a list in which a predicate holds for all elements" $ do+      dropWhileEnd (== ' ') "foo "    `shouldBe` "foo"+      dropWhileEnd (== ' ') "foo bar" `shouldBe` "foo bar"+  describe "isSubsequenceOf" $ do+    it "returns True if the first list is a subsequence of the second list" $ do+      isSubsequenceOf "GHC" "The Glorious Haskell Compiler" `shouldBe` True+      isSubsequenceOf "JHC" "The Glorious Haskell Compiler" `shouldBe` False+  describe "nub" $+    it "preserves the order of arguments to (==)" $+      nub [A, B] `shouldBe` [A]+  describe "nubBy" $+    it "preserves the order of arguments to the equality function" $+      nubBy (<) "12" `shouldBe` "1"+  describe "sortOn" $ do+    it "sorts a list by comparing the results of a key function applied to each element" $ do+      sortOn (>='b') "cba" `shouldBe` "acb"+  describe "uncons" $ do+    it "decomposes a list into its head and tail" $ do+      uncons ""   `shouldBe` Nothing+      uncons "12" `shouldBe` Just ('1', "2")+  describe "union" $+    it "nubs arguments in the same order as (==)" $ do+      union [A] [A, B] `shouldBe` [A]+  describe "unionBy" $+    it "nubs arguments in the same order as nubBy's equality function" $ do+      unionBy (<) "1" "21" `shouldBe` "11"
+ test/Data/Monoid/CompatSpec.hs view
@@ -0,0 +1,16 @@+module Data.Monoid.CompatSpec (main, spec) where++import           Test.Hspec+import           Test.QuickCheck++import           Data.Monoid.Compat++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+  describe "<>" $ do+    it "is an infix synonym for mappend" $ do+      property $ \xs ys -> do+        xs <> ys `shouldBe` (mappend xs ys :: String)
+ test/Data/STRef/CompatSpec.hs view
@@ -0,0 +1,19 @@+module Data.STRef.CompatSpec (main, spec) where++import           Test.Hspec++import           Control.Monad+import           Control.Monad.ST+import           Data.STRef.Compat++main :: IO ()+main = hspec spec++spec :: Spec+spec =+  describe "modifySTRef'" $+    it "should mutate the contents of an STRef strictly" $+      shouldBe (1000000 :: Int) $ runST $ do+        ref <- newSTRef 0+        replicateM_ 1000000 $ modifySTRef' ref (+1)+        readSTRef ref
+ test/Data/Version/CompatSpec.hs view
@@ -0,0 +1,10 @@+module Data.Version.CompatSpec (spec) where++import           Test.Hspec+import           Data.Version.Compat++spec :: Spec+spec = do+  describe "makeVersion" $+    it "constructs a tagless Version" $+      makeVersion [1,2,3] `shouldBe` Version [1,2,3] []
+ test/Data/Word/CompatSpec.hs view
@@ -0,0 +1,22 @@+module Data.Word.CompatSpec (main, spec) where++import Test.Hspec+import Data.Word.Compat++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+  describe "byteSwap16" $+    it "reverses the order of bytes in a Word16 value" $ do+      byteSwap16 0x1100 `shouldBe` 0x0011+      byteSwap16 0x1010 `shouldBe` 0x1010+  describe "byteSwap32" $+    it "reverses the order of bytes in a Word32 value" $ do+      byteSwap32 0x11001010 `shouldBe` 0x10100011+      byteSwap32 0x10101111 `shouldBe` 0x11111010+  describe "byteSwap64" $+    it "reverses the order of bytes in a Word64 value" $ do+      byteSwap64 0x1010111110101111 `shouldBe` 0x1111101011111010+      byteSwap64 0x1100000000000011 `shouldBe` 0x1100000000000011
+ test/Foreign/Marshal/Alloc/CompatSpec.hs view
@@ -0,0 +1,17 @@+module Foreign.Marshal.Alloc.CompatSpec (main, spec) where++import           Test.Hspec++import           Control.Exception+import           Foreign.Marshal.Alloc.Compat+import           Foreign.Storable++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+  describe "calloc" $+    it "allocates memory with bytes of value zero" $ do+      bracket calloc free $ \ptr -> do+        peek ptr `shouldReturn` (0 :: Int)
+ test/Foreign/Marshal/Utils/CompatSpec.hs view
@@ -0,0 +1,20 @@+module Foreign.Marshal.Utils.CompatSpec (main, spec) where++import Test.Hspec++import Foreign.Marshal.Alloc+import Foreign.Marshal.Utils.Compat+import Foreign.Ptr+import Foreign.Storable++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+  describe "fillBytes" $+    it "fills a given number of bytes in memory area with a byte value" $ do+      alloca $ \ptr -> do+        let _ = ptr :: Ptr Int+        fillBytes ptr 0 $ sizeOf ptr+        peek ptr `shouldReturn` 0
+ test/Numeric/CompatSpec.hs view
@@ -0,0 +1,24 @@+module Numeric.CompatSpec (main, spec) where++import Test.Hspec+import Numeric.Compat++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+  describe "showFFloatAlt" $ do+    it "shows a RealFloat value, always using decimal notation" $+      showFFloatAlt Nothing  (12 :: Double) "" `shouldBe` "12.0"+    it "allows to specify the number of decimal places" $+      showFFloatAlt (Just 4) (12 :: Double) "" `shouldBe` "12.0000"+  describe "showGFloatAlt" $ do+    it "shows a RealFloat value, using decimal notation if the absolute value lies between 0.1 and 9,999,999" $+      showGFloatAlt Nothing  (12 :: Double) ""         `shouldBe` "12.0"+    it "shows a RealFloat value, using decimal notation and specifying the number of decimal places" $+      showGFloatAlt (Just 4) (12 :: Double) ""         `shouldBe` "12.0000"+    it "shows a RealFloat value, using scientific notation if the absolute value falls outside of the range" $+      showGFloatAlt Nothing  (1234567890 :: Double) "" `shouldBe` "1.23456789e9"+    it "shows a RealFloat value, using scientific notation and specifying the number of decimal places" $+      showGFloatAlt (Just 4) (1234567890 :: Double) "" `shouldBe` "1.2346e9"
+ test/System/Environment/CompatSpec.hs view
@@ -0,0 +1,120 @@+{-# LANGUAGE CPP #-}+module System.Environment.CompatSpec (main, spec) where++import           Test.Hspec+import           Test.QuickCheck++import qualified Control.Exception as E+import           GHC.IO.Exception (IOErrorType (InvalidArgument))+import           System.Environment.Compat+import           System.IO.Error++main :: IO ()+main = hspec spec++withEnv :: String -> String -> IO a -> IO a+withEnv k v action = E.bracket save restore $ \_ -> do+  setEnv k v >> action+  where+    save    = lookupEnv k+    restore = maybe (unsetEnv k) (setEnv k)++withoutEnv :: String -> IO a -> IO a+withoutEnv k action = E.bracket save restore $ \_ -> do+  unsetEnv k >> action+  where+    save    = lookupEnv k+    restore = maybe (unsetEnv k) (setEnv k)++spec :: Spec+spec = do+  describe "lookupEnv" $ do+    it "returns specified environment variable" $ do+      withEnv "FOOBAR" "23" $ do+        lookupEnv "FOOBAR" `shouldReturn` Just "23"++    it "returns Nothing if specified environment variable is not set" $ do+      withoutEnv "FOOBAR" $ do+        lookupEnv "FOOBAR" `shouldReturn` Nothing++  describe "unsetEnv" $ do+    it "removes specified environment variable" $ do+      setEnv "FOO" "foo"+      unsetEnv "FOO"+      getEnv "FOO" `shouldThrow` isDoesNotExistError++    it "does nothing if specified environment variable is not set" $ do+      unsetEnv "BAR"+      unsetEnv "BAR"+      getEnv "BAR" `shouldThrow` isDoesNotExistError++    it "throws an exception if key is the empty string" $ do+      unsetEnv "" `shouldThrow` (== InvalidArgument) . ioeGetErrorType++    it "throws an exception if key contains '='" $ do+      unsetEnv "some=key" `shouldThrow` (== InvalidArgument) . ioeGetErrorType++    it "works for arbitrary keys" $+      property $ \k -> ('\NUL' `notElem` k && '=' `notElem` k && (not . null) k) ==> do+        setEnv k "foo"+        unsetEnv k+        getEnv k `shouldThrow` isDoesNotExistError++  describe "setEnv" $ do+    it "sets specified environment variable to given value" $ do+      unsetEnv "FOO"+      setEnv "FOO" "foo"+      getEnv "FOO" `shouldReturn` "foo"++    it "resets specified environment variable, if it is already set" $ do+      unsetEnv "FOO"+      setEnv "FOO" "foo"+      setEnv "FOO" "bar"+      getEnv "FOO" `shouldReturn` "bar"++    it "removes specified environment variable when value is the empty string" $ do+      setEnv "FOO" "foo"+      setEnv "FOO" ""+      getEnv "FOO" `shouldThrow` isDoesNotExistError++    it "removes specified environment variable when first character of value is NUL" $ do+      setEnv "FOO" "foo"+      setEnv "FOO" "\NULfoo"+      getEnv "FOO" `shouldThrow` isDoesNotExistError++    it "truncates value at NUL character" $ do+      unsetEnv "FOO"+      setEnv "FOO" "foo\NULbar"+      getEnv "FOO" `shouldReturn` "foo"++    it "truncates key at NUL character" $ do+      unsetEnv "FOO"+      setEnv "FOO\NULBAR" "foo"+      getEnv "FOO" `shouldReturn` "foo"++#if __GLASGOW_HASKELL__ >= 702+    it "works for unicode" $ do+      unsetEnv "FOO"+      setEnv "FOO" "foo-\955-bar"+      getEnv "FOO" `shouldReturn` "foo-\955-bar"+#endif++    it "works for arbitrary values" $+      property $ \v -> ('\NUL' `notElem` v && (not . null) v) ==> do+        setEnv "FOO" v+        getEnv "FOO" `shouldReturn` v++    it "works for unicode keys" $ do+      setEnv "foo-\955-bar" "foo"+      getEnv "foo-\955-bar" `shouldReturn` "foo"++    it "throws an exception if key is the empty string" $ do+      setEnv "" "foo" `shouldThrow` (== InvalidArgument) . ioeGetErrorType++    it "throws an exception if key contains '='" $ do+      setEnv "some=key" "foo" `shouldThrow` (== InvalidArgument) . ioeGetErrorType++    it "works for arbitrary keys" $+      property $ \k -> ('\NUL' `notElem` k && '=' `notElem` k && (not . null) k) ==> do+        setEnv k "foo"+        getEnv k `shouldReturn` "foo"
+ test/Text/Read/CompatSpec.hs view
@@ -0,0 +1,24 @@+module Text.Read.CompatSpec (main, spec) where++import           Test.Hspec++import           Text.Read.Compat++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+  describe "readMaybe" $ do+    it "parses a value" $ do+      readMaybe "23" `shouldBe` (Just 23 :: Maybe Int)++    it "returns Nothing if parsing fails" $ do+      readMaybe "xx" `shouldBe` (Nothing :: Maybe Int)++  describe "readEither" $ do+    it "parses a value" $ do+      readEither "23" `shouldBe` (Right 23 :: Either String Int)++    it "returns Left if parsing fails" $ do+      readEither "xx" `shouldBe` (Left "Prelude.read: no parse" :: Either String Int)